(*$L+*) (*$I XCOMP:A.TEXT *) (*$U-*) PROGRAM PASCALSYSTEM; (************************************************) (* *) (* UCSD PASCAL COMPILER *) (* *) (* BASED ON ZURICH P2 PORTABLE *) (* COMPILER, EXTENSIVLY *) (* MODIFIED BY ROGER T. SUMNER *) (* 1976..1977 *) (* *) (* INSTITUTE FOR INFORMATION SYSTEMS *) (* UC SAN DIEGO, LA JOLLA, CA *) (* *) (* KENNETH L. BOWLES, DIRECTOR *) (* *) (* THIS SOFTWARE IS THE PROPERTY OF THE *) (* REGENTS OF THE UNIVERSITY OF CALIFORNIA. *) (* *) (************************************************) TYPE PHYLE = FILE; INFOREC = RECORD WORKSYM,WORKCODE: ^PHYLE; ERRSYM,ERRBLK,ERRNUM: INTEGER; STUPID: BOOLEAN END; PROGRAM PROCEDURE USERPROGRAM; BEGIN END (*USERPROGRAM*) ; PROGRAM PROCEDURE COMPILER(VAR USERINFO: INFOREC); CONST DISPLIMIT = 12; MAXLEVEL = 8; MAXADDR = 28000; INTSIZE = 1; REALSIZE = 2; BITSPERWD = 16; CHARSIZE = 1; BOOLSIZE = 1; PTRSIZE = 1; FILESIZE = 300; NILFILESIZE = 34; BITSPERCHR = 8; CHRSPERWD = 2; STRINGSIZE = 0; STRGLGTH = 255; MAXINT = 32767; DEFSTRGLGTH = 80; LCAFTERMARKSTACK = 1; EOL = 13; MAXCURSOR = 1023; MAXCODE = 1299; MAXJTAB = 24; MAXSEG = 15; MAXPROCNUM = 149; TYPE (*BASIC SYMBOLS*) SYMBOL = (IDENT,COMMA,COLON,SEMICOLON,LPARENT,RPARENT,DOSY,TOSY, DOWNTOSY,ENDSY,UNTILSY,OFSY,THENSY,ELSESY,BECOMES,LBRACK, RBRACK,ARROW,PERIOD,BEGINSY,IFSY,CASESY,REPEATSY,WHILESY, FORSY,WITHSY,GOTOSY,LABELSY,CONSTSY,TYPESY,VARSY,PROCSY, FUNCSY,PROGSY,FORWARDSY,INTCONST,REALCONST,STRINGCONST, NOTSY,MULOP,ADDOP,RELOP,SETSY,PACKEDSY,ARRAYSY,RECORDSY, FILESY,OTHERSY); OPERATOR = (MUL,RDIV,ANDOP,IDIV,IMOD,PLUS,MINUS,OROP,LTOP,LEOP, GEOP,GTOP,NEOP,EQOP,INOP,NOOP); SETOFSYS = SET OF SYMBOL; (*CONSTANTS*) CSTCLASS = (REEL,PSET,STRG,TRIX); CSP = ^ CONSTREC; CONSTREC = RECORD CASE CCLASS: CSTCLASS OF TRIX: (CSTVAL: ARRAY [1..8] OF INTEGER); REEL: (RVAL: REAL); PSET: (PVAL: SET OF 0..127); STRG: (SLGTH: 0..STRGLGTH; SVAL: PACKED ARRAY [1..STRGLGTH] OF CHAR) END; VALU = RECORD CASE BOOLEAN OF TRUE: (IVAL: INTEGER); FALSE: (VALP: CSP) END; (*DATA STRUCTURES*) BITRANGE = 0..BITSPERWD; OPRANGE = 0..127; CURSRANGE = 0..MAXCURSOR; PROCRANGE = 0..MAXPROCNUM; LEVRANGE = 0..MAXLEVEL; ADDRRANGE = 0..MAXADDR; JTABRANGE = 0..MAXJTAB; SEGRANGE = 0..MAXSEG; DISPRANGE = 0..DISPLIMIT; STRUCTFORM = (SCALAR,SUBRANGE,POINTER,POWER,ARRAYS, RECORDS,FILES,TAGFLD,VARIANT); DECLKIND = (STANDARD,DECLARED,SPECIAL); STP = ^ STRUCTURE; CTP = ^ IDENTIFIER; STRUCTURE = RECORD SIZE: ADDRRANGE; CASE FORM: STRUCTFORM OF SCALAR: (CASE SCALKIND: DECLKIND OF DECLARED: (FCONST: CTP)); SUBRANGE: (RANGETYPE: STP; MIN,MAX: VALU); POINTER: (ELTYPE: STP); POWER: (ELSET: STP); ARRAYS: (AELTYPE,INXTYPE: STP; CASE AISPACKD:BOOLEAN OF TRUE: (ELSPERWD,ELWIDTH: BITRANGE; CASE AISSTRNG: BOOLEAN OF TRUE:(MAXLENG: 1..STRGLGTH))); RECORDS: (FSTFLD: CTP; RECVAR: STP); FILES: (FILTYPE: STP); TAGFLD: (TAGFIELDP: CTP; FSTVAR: STP); VARIANT: (NXTVAR,SUBVAR: STP; VARVAL: VALU) END; (*NAMES*) IDCLASS = (TYPES,KONST,VARS,FIELD,PROC,FUNC); SETOFIDS = SET OF IDCLASS; IDKIND = (ACTUAL,FORMAL); ALPHA = PACKED ARRAY [1..8] OF CHAR; IDENTIFIER = RECORD NAME: ALPHA; LLINK, RLINK: CTP; IDTYPE: STP; NEXT: CTP; CASE KLASS: IDCLASS OF KONST: (VALUES: VALU); VARS: (VKIND: IDKIND; VLEV: LEVRANGE; VADDR: ADDRRANGE); FIELD: (FLDADDR: ADDRRANGE; CASE FISPACKD: BOOLEAN OF TRUE: (FLDRBIT,FLDWIDTH: BITRANGE)); PROC, FUNC: (CASE PFDECKIND: DECLKIND OF SPECIAL: (KEY: 1..23); STANDARD: (CSPNUM: 1..40); DECLARED: (PFLEV: LEVRANGE; PFNAME: PROCRANGE; PFSEG: SEGRANGE; CASE PFKIND: IDKIND OF ACTUAL: (LOCALLC: ADDRRANGE; FORWDECL, INSCOPE: BOOLEAN))) END; WHERE = (BLCK,CREC,VREC,REC); (*EXPRESSIONS*) ATTRKIND = (CST,VARBL,EXPR); VACCESS = (DRCT,INDRCT,PACKD,MULTI,BYTE); ATTR = RECORD TYPTR: STP; CASE KIND: ATTRKIND OF CST: (CVAL: VALU); VARBL: (CASE ACCESS: VACCESS OF DRCT: (VLEVEL: LEVRANGE; DPLMT: ADDRRANGE); INDRCT: (IDPLMT: ADDRRANGE)) END; TESTP = ^ TESTPOINTER; TESTPOINTER = RECORD ELT1,ELT2 : STP; LASTTESTP : TESTP END; (*LABELS*) LBP = ^ CODELABEL; CODELABEL = RECORD CASE DEFINED: BOOLEAN OF FALSE: (REFLIST: ADDRRANGE); TRUE: (OCCURIC: ADDRRANGE; JTABINX: JTABRANGE) END; LABELP = ^ USERLABEL; USERLABEL = RECORD LABVAL: INTEGER; NEXTLAB: LABELP; CODELBP: LBP END; CODEARRAY = PACKED ARRAY [0..MAXCODE] OF CHAR; SYMBUFARRAY = PACKED ARRAY [CURSRANGE] OF CHAR; (*--------------------------------------------------------------------*) VAR CODEP: ^ CODEARRAY; (*CODE BUFFER UNTIL WRITEOUT*) SYMBUFP: ^ SYMBUFARRAY; (*SYMBOLIC BUFFER...ASCII OR CODED*) GATTR: ATTR; (*DESCRIBES CURRENT EXPRESSION*) VAL: VALU; (*VALUE OF LAST CONSTANT*) DISX, (*LEVEL OF LAST ID SEARCHED*) TOP: DISPRANGE; (*TOP OF DISPLAY*) (*SCANNER GLOBALS...NEXT FOUR VARS*) (*MUST BE IN THIS ORDER FOR IDSEARCH*) SYMCURSOR: CURSRANGE; (*CURRENT SCANNING INDEX IN SYMBUFP^*) SY: SYMBOL; (*SYMBOL FOUND BY INSYMBOL*) OP: OPERATOR; (*CLASSIFICATION OF LAST SYMBOL*) ID: ALPHA; (*LAST IDENTIFIER FOUND*) LGTH: INTEGER; (*LENGTH OF LAST STRING CONSTANT*) LCMAX,LC,IC: ADDRRANGE; (*LOCATION AND INSTRUCT COUNTERS*) (*SWITCHES:*) PRTERR,GOTOOK,RANGECHECK,CODEINSEG,IOCHECK, LIST,TEST,SYSCOMP,DP,INCLUDING: BOOLEAN; (*POINTERS:*) INTPTR,REALPTR,CHARPTR,BOOLPTR, TEXTPTR,NILPTR,STRGPTR: STP; (*POINTERS TO STANDARD IDS*) UTYPPTR,UCSTPTR,UVARPTR, UFLDPTR,UPRCPTR,UFCTPTR, (*POINTERS TO UNDECLARED IDS*) INPUTPTR,OUTPUTPTR, OUTERBLOCK,FWPTR: CTP; GLOBTESTP: TESTP; (*LAST TESTPOINTER*) LEVEL: LEVRANGE; (*CURRENT STATIC LEVEL*) SEG,NEXTSEG: SEGRANGE; (*CURRENT SEGMENT #*) SEGINX: INTEGER; (*CURRENT INDEX IN SEGMENT*) SCONST: CSP; (*INSYMBOL STRING RESULTS*) LOWTIME,LINEINFO,SCREENDOTS,STARTDOTS,SYMBLK: INTEGER; LINESTART: CURSRANGE; CURPROC,NEXTPROC: PROCRANGE; (*PROCEDURE NUMBER ASSIGNMENT*) CONSTBEGSYS,SIMPTYPEBEGSYS,TYPEBEGSYS,BLOCKBEGSYS, SELECTSYS,FACBEGSYS,STATBEGSYS,TYPEDELS: SETOFSYS; DISPLAY: ARRAY [DISPRANGE] OF RECORD FNAME: CTP; CASE OCCUR: WHERE OF BLCK: (FFILE: CTP; FLABEL: LABELP); CREC: (CLEV: LEVRANGE; CDSPL: ADDRRANGE); VREC: (VDSPL: ADDRRANGE) END; PROCTABLE: ARRAY [PROCRANGE] OF INTEGER; SEGTABLE: ARRAY [SEGRANGE] OF RECORD DISKADDR,CODELENG: INTEGER; SEGNAME: ALPHA END (*SEGTABLE*) ; NEXTJTAB: JTABRANGE; JTAB: ARRAY [JTABRANGE] OF INTEGER; OLDSYMBLK: INTEGER; OLDSYMCURSOR: CURSRANGE; INCLFILE: FILE; CURBYTE, CURBLK: INTEGER; DISKBUF: PACKED ARRAY [0..511] OF CHAR; (*--------------------------------------------------------------------*) PROCEDURE INSYMBOL; FORWARD; PROCEDURE ERROR(ERRORNUM: INTEGER); FORWARD; PROCEDURE ENTERID(FCP: CTP); FORWARD; PROCEDURE GETNEXTPAGE; FORWARD; PROGRAM PROCEDURE COMPINIT; PROCEDURE ENTSTDTYPES; VAR SP: STP; BEGIN NEW(INTPTR,SCALAR,STANDARD); WITH INTPTR^ DO BEGIN SIZE := INTSIZE; FORM := SCALAR; SCALKIND := STANDARD END; NEW(REALPTR,SCALAR,STANDARD); WITH REALPTR^ DO BEGIN SIZE := REALSIZE; FORM := SCALAR; SCALKIND := STANDARD END; NEW(CHARPTR,SCALAR,STANDARD); WITH CHARPTR^ DO BEGIN SIZE := CHARSIZE; FORM := SCALAR; SCALKIND := STANDARD END; NEW(BOOLPTR,SCALAR,DECLARED); WITH BOOLPTR^ DO BEGIN SIZE := BOOLSIZE; FORM := SCALAR; SCALKIND := DECLARED END; NEW(NILPTR,POINTER); WITH NILPTR^ DO BEGIN SIZE := PTRSIZE; FORM := POINTER; ELTYPE := NIL END; NEW(TEXTPTR,FILES); WITH TEXTPTR^ DO BEGIN SIZE := FILESIZE+CHARSIZE; FORM := FILES; FILTYPE := CHARPTR END; NEW(STRGPTR,ARRAYS,TRUE,TRUE); WITH STRGPTR^ DO BEGIN FORM := ARRAYS; SIZE := (DEFSTRGLGTH + CHRSPERWD) DIV CHRSPERWD; AISPACKD := TRUE; AISSTRNG := TRUE; INXTYPE := INTPTR; ELWIDTH := BITSPERCHR; ELSPERWD := CHRSPERWD; AELTYPE := CHARPTR; MAXLENG := DEFSTRGLGTH; END END (*ENTSTDTYPES*) ; PROCEDURE ENTSTDNAMES; VAR CP,CP1: CTP; I: INTEGER; BEGIN NEW(CP,TYPES); WITH CP^ DO BEGIN NAME := 'INTEGER '; IDTYPE := INTPTR; KLASS := TYPES END; ENTERID(CP); NEW(CP,TYPES); WITH CP^ DO BEGIN NAME := 'REAL '; IDTYPE := REALPTR; KLASS := TYPES END; ENTERID(CP); NEW(CP,TYPES); WITH CP^ DO BEGIN NAME := 'CHAR '; IDTYPE := CHARPTR; KLASS := TYPES END; ENTERID(CP); NEW(CP,TYPES); WITH CP^ DO BEGIN NAME := 'BOOLEAN '; IDTYPE := BOOLPTR; KLASS := TYPES END; ENTERID(CP); NEW(CP,TYPES); WITH CP^ DO BEGIN NAME := 'STRING '; IDTYPE := STRGPTR; KLASS := TYPES END; ENTERID(CP); NEW(CP,TYPES); WITH CP^ DO BEGIN NAME := 'TEXT '; IDTYPE := TEXTPTR; KLASS := TYPES END; ENTERID(CP); NEW(INPUTPTR,VARS); WITH INPUTPTR^ DO BEGIN NAME := 'INPUT '; IDTYPE := TEXTPTR; KLASS := VARS; VKIND := FORMAL; VLEV := 0; VADDR := 2 END; ENTERID(INPUTPTR); NEW(OUTPUTPTR,VARS); WITH OUTPUTPTR^ DO BEGIN NAME := 'OUTPUT '; IDTYPE := TEXTPTR; KLASS := VARS; VKIND := FORMAL; VLEV := 0; VADDR := 3 END; ENTERID(OUTPUTPTR); NEW(CP,VARS); WITH CP^ DO BEGIN NAME := 'KEYBOARD'; IDTYPE := TEXTPTR; KLASS := VARS; VKIND := FORMAL; VLEV := 0; VADDR := 4 END; ENTERID(CP); CP1 := NIL; FOR I := 0 TO 1 DO BEGIN NEW(CP,KONST); WITH CP^ DO BEGIN IDTYPE := BOOLPTR; IF I = 0 THEN NAME := 'FALSE ' ELSE NAME := 'TRUE '; NEXT := CP1; VALUES.IVAL := I; KLASS := KONST END; ENTERID(CP); CP1 := CP END; BOOLPTR^.FCONST := CP; NEW(CP,KONST); WITH CP^ DO BEGIN NAME := 'NIL '; IDTYPE := NILPTR; NEXT := NIL; VALUES.IVAL := 0; KLASS := KONST END; ENTERID(CP); END (*ENTSTDNAMES*) ; PROCEDURE ENTUNDECL; BEGIN NEW(UTYPPTR,TYPES); WITH UTYPPTR^ DO BEGIN NAME := ' '; IDTYPE := NIL; KLASS := TYPES END; NEW(UCSTPTR,KONST); WITH UCSTPTR^ DO BEGIN NAME := ' '; IDTYPE := NIL; NEXT := NIL; VALUES.IVAL := 0; KLASS := KONST END; NEW(UVARPTR,VARS); WITH UVARPTR^ DO BEGIN NAME := ' '; IDTYPE := NIL; VKIND := ACTUAL; NEXT := NIL; VLEV := 0; VADDR := 0; KLASS := VARS END; NEW(UFLDPTR,FIELD); WITH UFLDPTR^ DO BEGIN NAME := ' '; IDTYPE := NIL; NEXT := NIL; FLDADDR := 0; KLASS := FIELD END; NEW(UPRCPTR,PROC,DECLARED,ACTUAL); WITH UPRCPTR^ DO BEGIN NAME := ' '; IDTYPE := NIL; FORWDECL := FALSE; NEXT := NIL; INSCOPE := FALSE; LOCALLC := 0; PFLEV := 0; PFNAME := 0; PFSEG := 0; KLASS := PROC; PFDECKIND := DECLARED; PFKIND := ACTUAL END; NEW(UFCTPTR,FUNC,DECLARED,ACTUAL); WITH UFCTPTR^ DO BEGIN NAME := ' '; IDTYPE := NIL; NEXT := NIL; FORWDECL := FALSE; INSCOPE := FALSE; LOCALLC := 0; PFLEV := 0; PFNAME := 0; PFSEG := 0; KLASS := FUNC; PFDECKIND := DECLARED; PFKIND := ACTUAL END END (*ENTUNDECL*) ; PROCEDURE ENTSPCPROCS; VAR LCP: CTP; I: INTEGER; ISFUNC: BOOLEAN; NA: ARRAY [1..42] OF ALPHA; BEGIN NA[ 1] := 'READ '; NA[ 2] := 'READLN '; NA[ 3] := 'WRITE '; NA[ 4] := 'WRITELN '; NA[ 5] := 'EOF '; NA[ 6] := 'EOLN '; NA[ 7] := 'PRED '; NA[ 8] := 'SUCC '; NA[ 9] := 'ORD '; NA[10] := 'SQR '; NA[11] := 'ABS '; NA[12] := 'NEW '; NA[13] := 'UNITREAD'; NA[14] := 'UNITWRIT'; NA[15] := 'CONCAT '; NA[16] := 'LENGTH '; NA[17] := 'INSERT '; NA[18] := 'DELETE '; NA[19] := 'COPY '; NA[20] := 'POS '; NA[21] := 'MOVELEFT'; NA[22] := 'MOVERIGH'; NA[23] := 'EXIT '; NA[24] := 'IDSEARCH'; NA[25] := 'TREESEAR'; NA[26] := 'TIME '; NA[27] := 'FILLCHAR'; NA[28] := 'OPENNEW '; NA[29] := 'OPENOLD '; NA[30] := 'REWRITE '; NA[31] := 'CLOSE '; NA[32] := 'SEEK '; NA[33] := 'RESET '; NA[34] := 'GET '; NA[35] := 'PUT '; NA[36] := 'SCAN '; NA[37] := 'BLOCKREA'; NA[38] := 'BLOCKWRI'; NA[39] := 'DRAWLINE'; NA[40] := 'PAGE '; NA[41] := 'SIZEOF '; NA[42] := 'DRAWBLOC'; FOR I := 1 TO 42 DO BEGIN ISFUNC := I IN [5,6,7,8,9,10,11,15,16,19,20,25,36,37,38,41]; IF ISFUNC THEN NEW(LCP,FUNC,SPECIAL) ELSE NEW(LCP,PROC,SPECIAL); WITH LCP^ DO BEGIN NAME := NA[I]; NEXT := NIL; IDTYPE := NIL; IF ISFUNC THEN KLASS := FUNC ELSE KLASS := PROC; PFDECKIND := SPECIAL; KEY := I END; ENTERID(LCP) END END (*ENTSPCPROCS*) ; PROCEDURE ENTSTDPROCS; VAR LCP,PARAM: CTP; LSP,FTYPE: STP; I: INTEGER; ISPROC: BOOLEAN; NA: ARRAY [1..19] OF ALPHA; BEGIN NA[ 1] := 'ODD '; NA[ 2] := 'CHR '; NA[ 3] := 'TRUNC '; NA[ 4] := 'ROUND '; NA[ 5] := 'SIN '; NA[ 6] := 'COS '; NA[ 7] := 'LOG '; NA[ 8] := 'ATAN '; NA[ 9] := 'LN '; NA[10] := 'EXP '; NA[11] := 'SQRT '; NA[12] := 'MARK '; NA[13] := 'RELEASE '; NA[14] := 'IORESULT'; NA[15] := 'UNITBUSY'; NA[16] := 'PWROFTEN'; NA[17] := 'UNITWAIT'; NA[18] := 'UNITCLEA'; NA[19] := 'HALT '; FOR I := 1 TO 19 DO BEGIN ISPROC := I IN [12,13,17,18,19]; CASE I OF 1: BEGIN FTYPE := BOOLPTR; NEW(PARAM,VARS); WITH PARAM^ DO BEGIN IDTYPE := INTPTR; VKIND := ACTUAL END; END; 2: FTYPE := CHARPTR; 3: BEGIN FTYPE := INTPTR; NEW(PARAM,VARS); WITH PARAM^ DO BEGIN IDTYPE := REALPTR; VKIND := ACTUAL END; END; 5: FTYPE := REALPTR; 12: BEGIN FTYPE := NIL; NEW(PARAM,VARS); NEW(LSP,POINTER); WITH LSP^ DO BEGIN SIZE := PTRSIZE; FORM := POINTER; ELTYPE := NIL END; WITH PARAM^ DO BEGIN IDTYPE := LSP; VKIND := FORMAL END; END; 14: BEGIN FTYPE := INTPTR; PARAM := NIL END; 15: BEGIN FTYPE := BOOLPTR; NEW(PARAM,VARS); WITH PARAM^ DO BEGIN IDTYPE := INTPTR; VKIND := ACTUAL END; END; 16: FTYPE := REALPTR; 17: FTYPE := NIL; 19: BEGIN FTYPE := NIL; PARAM := NIL END; END (*PARAM AND TYPE CASES*) ; IF ISPROC THEN NEW(LCP,PROC,STANDARD) ELSE NEW(LCP,FUNC,STANDARD); WITH LCP^ DO BEGIN NAME := NA[I]; PFDECKIND := STANDARD; CSPNUM := I + 20; IF ISPROC THEN KLASS := PROC ELSE KLASS := FUNC; IF PARAM <> NIL THEN WITH PARAM^ DO BEGIN KLASS := VARS; NEXT := NIL END; IDTYPE := FTYPE; NEXT := PARAM END; ENTERID(LCP) END END (*ENTSTDPROCS*) ; PROCEDURE INITSCALARS; BEGIN FWPTR := NIL; GLOBTESTP := NIL; LINESTART := 0; LINEINFO := LCAFTERMARKSTACK; LIST := FALSE; SYMBLK := 2; SCREENDOTS := 0; STARTDOTS := 0; FOR SEG := 0 TO MAXSEG DO WITH SEGTABLE[SEG] DO BEGIN DISKADDR := 0; CODELENG := 0; SEGNAME := ' ' END; LC := LCAFTERMARKSTACK; IOCHECK := TRUE; DP := TRUE; SEGINX := 0; NEXTJTAB := 1; NEXTPROC := 2; CURPROC := 1; NEW(SCONST); NEW(SYMBUFP); NEW(CODEP); SEG := 1; NEXTSEG := 10; CURBLK := 1; CURBYTE := 0; GOTOOK := FALSE; RANGECHECK := TRUE; SYSCOMP := FALSE; CODEINSEG := FALSE; PRTERR := TRUE; INCLUDING := FALSE END (*INITSCALARS*) ; PROCEDURE INITSETS; BEGIN CONSTBEGSYS := [ADDOP,INTCONST,REALCONST,STRINGCONST,IDENT]; SIMPTYPEBEGSYS := [LPARENT] + CONSTBEGSYS; TYPEBEGSYS := [ARROW,PACKEDSY,ARRAYSY,RECORDSY,SETSY,FILESY] + SIMPTYPEBEGSYS; TYPEDELS := [ARRAYSY,RECORDSY,SETSY,FILESY]; BLOCKBEGSYS := [LABELSY,CONSTSY,TYPESY,VARSY,PROCSY,FUNCSY,PROGSY,BEGINSY]; SELECTSYS := [ARROW,PERIOD,LBRACK]; FACBEGSYS := [INTCONST,REALCONST,STRINGCONST,IDENT,LPARENT,LBRACK,NOTSY]; STATBEGSYS := [BEGINSY,GOTOSY,IFSY,WHILESY,REPEATSY,FORSY,WITHSY,CASESY] END (*INITSETS*) ; BEGIN (*COMPINIT*) INITSCALARS; INITSETS; LEVEL := 0; TOP := 0; WITH DISPLAY[0] DO BEGIN FNAME := NIL; FFILE := NIL; FLABEL := NIL; OCCUR := BLCK END; ENTSTDTYPES; ENTSTDNAMES; ENTUNDECL; ENTSPCPROCS; ENTSTDPROCS; GETNEXTPAGE; UNITWRITE(3,PROCTABLE[-1200],35); FOR IC := 1 TO 7 DO WRITELN(OUTPUT); WRITELN(OUTPUT,'PASCAL compilation'); WRITE(OUTPUT,'< 0>'); INSYMBOL; IF SYSCOMP THEN BEGIN OUTERBLOCK := NIL; SEG := 0; NEXTSEG := 1 END ELSE BEGIN TOP := 1; LEVEL := 1; WITH DISPLAY[1] DO BEGIN FNAME := NIL; FFILE := NIL; FLABEL := NIL; OCCUR := BLCK END; LC := LC+2; (*KEEP STACK STRAIGHT FOR NOW*) NEW(OUTERBLOCK,PROC,DECLARED,ACTUAL); WITH OUTERBLOCK^ DO BEGIN NEXT := NIL; LOCALLC := LC; NAME := 'PROGRAM '; IDTYPE := NIL; KLASS := PROC; PFDECKIND := DECLARED; PFLEV := 0; PFNAME := 1; PFSEG := SEG; PFKIND := ACTUAL; FORWDECL := FALSE; INSCOPE := TRUE END END; IF SY = PROGSY THEN BEGIN INSYMBOL; IF SY = IDENT THEN BEGIN SEGTABLE[SEG].SEGNAME := ID; IF OUTERBLOCK <> NIL THEN OUTERBLOCK^.NAME := ID; END ELSE ERROR(2); INSYMBOL; IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14) END END (*COMPINIT*) ; (*$I XCOMP:B.TEXT *) PROCEDURE ERROR(*ERRORNUM: INTEGER*); VAR CH: CHAR; BEGIN WITH USERINFO DO IF (ERRSYM <> SYMCURSOR) OR (ERRBLK <> SYMBLK) THEN BEGIN ERRSYM := SYMCURSOR; ERRBLK := SYMBLK; ERRNUM := ERRORNUM; IF STUPID THEN EXIT(COMPILER); WRITELN(OUTPUT); CH := ' '; WRITE(OUTPUT,SYMBUFP^:SYMCURSOR) WRITELN(OUTPUT,' <<<<' Error # ',ERRORNUM:0); WRITE(OUTPUT,'Hit to continue'); REPEAT UNITREAD(2,CH,1); UNTIL (CH = ' ') OR (CH = CHR(27)); IF (ERRORNUM > 400) OR (CH = CHR(27)) THEN EXIT(COMPILER); WRITELN(OUTPUT); WRITE(OUTPUT,'<',SCREENDOTS:4,'>') END END (*ERROR*) ; PROCEDURE GETNEXTPAGE; BEGIN SYMCURSOR := 0; IF INCLUDING THEN IF BLOCKREAD(INCLFILE,SYMBUFP^,0,SYMBLK) = 0 THEN BEGIN CLOSE(INCLFILE); INCLUDING := FALSE; SYMBLK := OLDSYMBLK; SYMCURSOR := OLDSYMCURSOR; LINESTART := SYMCURSOR (*AT CR...WILL PRINT EXTRA LINE*) END; IF NOT INCLUDING THEN IF BLOCKREAD(USERINFO.WORKSYM^,SYMBUFP^,2,SYMBLK) <> 2 THEN ERROR(401); SYMBLK := SYMBLK+2 END (*GETNEXTPAGE*) ; PROCEDURE PRINTLINE; VAR LPUNIT: INTEGER; A: PACKED ARRAY [0..1] OF CHAR; PROCEDURE WRITEINT(IVAL: INTEGER); VAR I,IPOT: INTEGER; CH: CHAR; ZAP: BOOLEAN; A: PACKED ARRAY [0..5] OF CHAR; BEGIN ZAP := TRUE; IPOT := 10000; A[0] := ' '; FOR I := 1 TO 5 DO BEGIN CH := CHR(IVAL DIV IPOT + ORD('0')); IF I <> 5 THEN IF ZAP THEN IF CH = '0' THEN CH := ' ' ELSE ZAP := FALSE; A[I] := CH; IVAL := IVAL MOD IPOT; IPOT := IPOT DIV 10 END; UNITWRITE(LPUNIT,A,6) END (*WRITEINT*) ; BEGIN LPUNIT := 6; (*PRINTLINE*) WRITEINT(SCREENDOTS); WRITEINT(CURPROC); A[0] := ':'; IF DP THEN A[1] := 'D' ELSE A[1] := 'C'; UNITWRITE(LPUNIT,A,2); WRITEINT(LINEINFO); A := ' '; UNITWRITE(LPUNIT,A,2); UNITWRITE(LPUNIT,A,2); UNITWRITE(LPUNIT,SYMBUFP^[LINESTART],SYMCURSOR-LINESTART,,TRUE) END (*PRINTLINE*) ; PROCEDURE STARTINCL; (*I APOLOGIZE FOR SUCH KLOODGE AS THIS BUT IT HAS TO BE IN RIGHT NOW...*) VAR TSTART,TLENG: INTEGER; TITLE: STRING[40]; BEGIN TSTART := SYMCURSOR+2; SYMCURSOR := SCAN(80,=CHR(EOL),SYMBUFP^[TSTART])+TSTART+1; TLENG := SYMCURSOR-TSTART-3; TITLE[0] := CHR(TLENG); MOVELEFT(SYMBUFP^[TSTART],TITLE[1],TLENG); OPENOLD(INCLFILE,TITLE); IF IORESULT <> 0 THEN BEGIN OPENOLD(INCLFILE,CONCAT(TITLE,'.TEXT')); IF IORESULT <> 0 THEN ERROR(403) END; SCREENDOTS := SCREENDOTS+1; IF LIST THEN PRINTLINE; INCLUDING := TRUE; OLDSYMCURSOR := SYMCURSOR-1; (*POINT AT CR...PREVENT END PAGE BLOWUP*) OLDSYMBLK := SYMBLK-2; (*SYMBLK IS NEXT TO READ...SAVE CUR PAGE#*) SYMBLK := 2; GETNEXTPAGE; LINESTART := SYMCURSOR; INSYMBOL; EXIT(INSYMBOL) (*WEIRD, ISNT IT...*) END (*STARTINCL*) ; PROCEDURE INSYMBOL; (* COMPILER VERSION 3.4 06-NOV-76 *) LABEL 1; VAR LVP: CSP; X: INTEGER; PROCEDURE CHECKEND; BEGIN (* CHECKS FOR THE END OF THE PAGE *) WRITE(OUTPUT,'.'); SCREENDOTS := SCREENDOTS+1; SYMCURSOR := SYMCURSOR + 1; IF (SCREENDOTS-STARTDOTS) MOD 50 = 0 THEN BEGIN WRITELN(OUTPUT); WRITE(OUTPUT,'<',SCREENDOTS:4,'>') END IF LIST THEN PRINTLINE; IF SYMBUFP^[SYMCURSOR]=CHR(0) THEN GETNEXTPAGE ELSE LINESTART := SYMCURSOR; IF SYMBUFP^[SYMCURSOR] = CHR(16(*DLE*)) THEN SYMCURSOR := SYMCURSOR+2 ELSE BEGIN SYMCURSOR := SYMCURSOR+SCAN(80,<>CHR(9),SYMBUFP^[SYMCURSOR]); SYMCURSOR := SYMCURSOR+SCAN(80,<>' ',SYMBUFP^[SYMCURSOR]) END; IF DP THEN LINEINFO := LC ELSE LINEINFO := IC END; PROCEDURE COMMENTER; VAR CH,SW,DEL: CHAR; BEGIN SYMCURSOR := SYMCURSOR+2; (* POINT TO THE FIRST CH PAST "(*" *) IF SYMBUFP^[SYMCURSOR]='$' THEN BEGIN IF SYMBUFP^[SYMCURSOR+1] <> '*' THEN REPEAT CH := SYMBUFP^[SYMCURSOR+1]; SW := SYMBUFP^[SYMCURSOR+2]; DEL := SYMBUFP^[SYMCURSOR+3]; CASE CH OF 'G': GOTOOK := (SW='+'); 'I': IF (SW='+') OR (SW='-') THEN IOCHECK := (SW='+') ELSE STARTINCL; 'L': LIST := (SW='+'); 'R': RANGECHECK := (SW='+'); 'U': BEGIN SYSCOMP := (SW = '-'); RANGECHECK := NOT SYSCOMP; IOCHECK := RANGECHECK; GOTOOK := SYSCOMP END END (*CASES*); SYMCURSOR := SYMCURSOR+3; UNTIL DEL <> ','; END; SYMCURSOR := SYMCURSOR-1; (* ADJUST *) REPEAT REPEAT SYMCURSOR := SYMCURSOR+1; WHILE SYMBUFP^[SYMCURSOR] = CHR(EOL) DO CHECKEND UNTIL SYMBUFP^[SYMCURSOR]='*'; UNTIL (SYMBUFP^[SYMCURSOR+1]=')') SYMCURSOR := SYMCURSOR+2; END (*COMMENTER*); PROCEDURE STRING; VAR T: PACKED ARRAY [1..80] OF CHAR; TP,NBLANKS,L: INTEGER; DUPLE: BOOLEAN; BEGIN DUPLE := FALSE; (* INDICATES WHEN '' IS PRESENT *) TP := 0; (* INDEX INTO TEMPORARY STRING *) REPEAT IF DUPLE THEN SYMCURSOR := SYMCURSOR+1; REPEAT SYMCURSOR := SYMCURSOR+1; TP := TP+1; IF SYMBUFP^[SYMCURSOR] = CHR(EOL) THEN BEGIN ERROR(202); CHECKEND END; T[TP] := SYMBUFP^[SYMCURSOR]; UNTIL SYMBUFP^[SYMCURSOR]=''''; DUPLE := TRUE; UNTIL SYMBUFP^[SYMCURSOR+1]<>''''; 1: TP := TP-1; (* ADJUST *) SY := STRINGCONST; OP := NOOP; LGTH := TP; (* GROSS *) IF TP=1 (* SINGLE CHARACTER CONSTANT *) THEN VAL.IVAL := ORD(T[1]) ELSE WITH SCONSTDO BEGIN CCLASS := STRG; SLGTH := TP; MOVELEFT(T[1],SVAL[1],TP); VAL.VALP := SCONST END END(*STRING*); PROCEDURE NUMBER; VAR EXPONENT,ENDI,ENDF,ENDE,SIGN,IPART,FPART,EPART, ISUM: INTEGER; TIPE: (REALTIPE,INTEGERTIPE); RSUM: REAL; J: INTEGER; BEGIN (* TAKES A NUMBER AND DECIDES WHETHER IT'S REAL OR INTEGER AND CONVERTS IT TO THE INTERNAL FORM. *) TIPE := INTEGERTIPE; ENDI := 0; ENDF := 0; ENDE := 0; SIGN := 1; EPART := 9999; (* OUT OF REACH *) IPART := SYMCURSOR; (* INTEGER PART STARTS HERE *) REPEAT SYMCURSOR := SYMCURSOR+1 UNTIL (SYMBUFP^[SYMCURSOR]<'0') OR (SYMBUFP^[SYMCURSOR]>'9'); (* SYMCURSOR NOW POINTS AT FIRST CHARACTER PAST INTEGER PART *) ENDI := SYMCURSOR-1; (* MARK THE END OF IPART *) IF SYMBUFP^[SYMCURSOR]='.' THEN IF SYMBUFP^[SYMCURSOR+1]<>'.' (* WATCH OUT FOR '..' *) THEN BEGIN TIPE := REALTIPE; SYMCURSOR := SYMCURSOR+1; FPART := SYMCURSOR; (* BEGINNING OF FPART *) REPEAT SYMCURSOR := SYMCURSOR+1; UNTIL (SYMBUFP^[SYMCURSOR]<'0') OR (SYMBUFP^[SYMCURSOR]>'9'); ENDF := SYMCURSOR-1; END; IF SYMBUFP^[SYMCURSOR]='E' THEN BEGIN TIPE := REALTIPE; SYMCURSOR := SYMCURSOR+1; IF SYMBUFP^[SYMCURSOR]='-' THEN BEGIN SYMCURSOR := SYMCURSOR+1; SIGN := -1; END ELSE IF SYMBUFP^[SYMCURSOR]='+' THEN SYMCURSOR := SYMCURSOR+1; EPART := SYMCURSOR; (* BEGINNING OF EXPONENT *) WHILE (SYMBUFP^[SYMCURSOR]>='0') AND (SYMBUFP^[SYMCURSOR]<='9') DO SYMCURSOR := SYMCURSOR+1; ENDE := SYMCURSOR-1; IF ENDE3276) OR ((ISUM=3276) AND (SYMBUFP^[J]>'7')) THEN BEGIN ERROR(203); J := ENDI END ELSE ISUM := ISUM*10+(ORD(SYMBUFP^[J])-ORD('0')); END; SY := INTCONST; OP := NOOP; VAL.IVAL := ISUM; END ELSE BEGIN (* REAL NUMBER HERE *) RSUM := 0; FOR J := IPART TO ENDI DO BEGIN RSUM := RSUM*10+(ORD(SYMBUFP^[J])-ORD('0')); END; FOR J := ENDF DOWNTO FPART DO RSUM := RSUM+(ORD(SYMBUFP^[J])-ORD('0'))/PWROFTEN(J-FPART+1); EXPONENT := 0; FOR J := EPART TO ENDE DO EXPONENT := EXPONENT*10+ORD(SYMBUFP^[J])-ORD('0'); IF SIGN=-1 THEN RSUM := RSUM/PWROFTEN(EXPONENT) ELSE RSUM := RSUM*PWROFTEN(EXPONENT); SY := REALCONST; OP := NOOP; NEW(LVP,REEL); LVP^.CCLASS := REEL; LVP^.RVAL := RSUM; VAL.VALP := LVP; END; SYMCURSOR := SYMCURSOR-1; (* ADJUST FOR POSTERITY *) END; BEGIN (* INSYMBOL *) OP := NOOP; 1: SY := OTHERSY; (* IF NO CASES EXERCISED BLOW UP *) CASE SYMBUFP^[SYMCURSOR] OF '''':STRING; '0','1','2','3','4','5','6','7','8','9': NUMBER; 'A','B','C','D','E','F','G','H','I','J','K','L', 'M',N','O','P','Q','R','S','T','U','V','W','X', 'Y','Z': IDSEARCH(SYMCURSOR,SYMBUFP^); (* MAGIC PROC *) '': BEGIN COMMENTER(''); GOTO 1 END; '(': BEGIN IF SYMBUFP^[SYMCURSOR+1]='*' THEN BEGIN COMMENTER; GOTO 1; (* GET ANOTHER TOKEN *) END ELSE SY := LPARENT; END; ')': SY := RPARENT; ',': SY := COMMA; ' ',' ': BEGIN SYMCURSOR := SYMCURSOR+1; GOTO 1; END; '.': BEGIN IF SYMBUFP^[SYMCURSOR+1]='.' THEN BEGIN SYMCURSOR := SYMCURSOR+1; SY := COLON END ELSE SY := PERIOD; END; ':': IF SYMBUFP^[SYMCURSOR+1]='=' THEN BEGIN SYMCURSOR := SYMCURSOR+1; SY := BECOMES; END ELSE SY := COLON; ';': SY := SEMICOLON; ','^': SY := ARROW; '[': SY := LBRACK; ']': SY := RBRACK; '*': BEGIN SY := MULOP; OP := MUL END; '+': BEGIN SY := ADDOP; OP := PLUS END; '-': BEGIN SY := ADDOP; OP := MINUS END; '/': BEGIN SY := MULOP; OP := RDIV END; '<': BEGIN SY := RELOP; OP := LTOP; CASE SYMBUFP^[SYMCURSOR+1] OF '>': BEGIN OP := NEOP; SYMCURSOR := SYMCURSOR+1 END; '=': BEGIN OP := LEOP; SYMCURSOR := SYMCURSOR+1 END END; END; '=': BEGIN SY := RELOP; OP := EQOP END; '>': BEGIN SY := RELOP; IF SYMBUFP^[SYMCURSOR+1]='=' THEN BEGIN OP := GEOP; SYMCURSOR := SYMCURSOR+1; END ELSE OP := GTOP; END END (* CASE SYMBUFP^[SYMCURSOR] OF *); IF SY=OTHERSY THEN IF SYMBUFP^[SYMCURSOR] = CHR(EOL) THEN BEGIN CHECKEND; GOTO 1 END ELSE ERROR(400); SYMCURSOR := SYMCURSOR+1; (* NEXT CALL TALKS ABOUT NEXT TOKEN *) END (*INSYMBOL*) ; PROCEDURE ENTERID(FCP: CTP); VAR LCP,LCP1: CTP; I: INTEGER; BEGIN LCP := DISPLAY[TOP].FNAME; IF LCP = NIL THEN DISPLAY[TOP].FNAME := FCP ELSE BEGIN I := TREESEARCH(LCP,LCP1,FCP^.NAME); WHILE I = 0 DO BEGIN ERROR(101); IF LCP1^.RLINK = NIL THEN I := 1 ELSE I := TREESEARCH(LCP1^.RLINK,LCP1,FCP^.NAME) END; IF I = 1 THEN LCP1^.RLINK := FCP ELSE LCP1^.LLINK := FCP END; FCP^.LLINK := NIL; FCP^.RLINK := NIL END (*ENTERID*) ; PROCEDURE SEARCHSECTION(FCP: CTP; VAR FCP1: CTP); BEGIN IF FCP <> NIL THEN IF TREESEARCH(FCP,FCP1,ID) = 0 THEN (*NADA*) ELSE FCP1 := NIL ELSE FCP1 := NIL END (*SEARCHSECTION*) ; PROCEDURE SEARCHID(FIDCLS: SETOFIDS; VAR FCP: CTP); LABEL 1; VAR LCP: CTP; BEGIN FOR DISX := TOP DOWNTO 0 DO BEGIN LCP := DISPLAY[DISX].FNAME; IF LCP <> NIL THEN IF TREESEARCH(LCP,LCP,ID) = 0 THEN IF LCP^.KLASS IN FIDCLS THEN GOTO 1 ELSE IF PRTERR THEN ERROR(103) ELSE LCP := NIL ELSE LCP := NIL END; IF PRTERR THEN BEGIN ERROR(104); IF TYPES IN FIDCLS THEN LCP := UTYPPTR ELSE IF VARS IN FIDCLS THEN LCP := UVARPTR ELSE IF FIELD IN FIDCLS THEN LCP := UFLDPTR ELSE IF KONST IN FIDCLS THEN LCP := UCSTPTR ELSE IF PROC IN FIDCLS THEN LCP := UPRCPTR ELSE LCP := UFCTPTR END; 1: FCP := LCP END (*SEARCHID*) ; PROCEDURE GETBOUNDS(FSP: STP; VAR FMIN,FMAX: INTEGER); BEGIN WITH FSP^ DO IF FORM = SUBRANGE THEN BEGIN FMIN := MIN.IVAL; FMAX := MAX.IVAL END ELSE BEGIN FMIN := 0; IF FSP = CHARPTR THEN FMAX := 255 ELSE IF FSP^.FCONST <> NIL THEN FMAX := FSP^.FCONST^.VALUES.IVAL ELSE FMAX := 0 END END (*GETBOUNDS*) ; PROCEDURE SKIP(FSYS: SETOFSYS); BEGIN WHILE NOT(SY IN FSYS) DO INSYMBOL END (*SKIP*) ; FUNCTION PAOFCHAR(FSP: STP): BOOLEAN; BEGIN PAOFCHAR := FALSE; IF FSP <> NIL THEN IF FSP^.FORM = ARRAYS THEN PAOFCHAR := FSP^.AISPACKD AND (FSP^.AELTYPE = CHARPTR) END (*PAOFCHAR*) ; FUNCTION STRGTYPE(FSP: STP) : BOOLEAN; BEGIN STRGTYPE := FALSE; IF PAOFCHAR(FSP) THEN STRGTYPE := FSP^.AISSTRNG END (*STRGTYPE*) ; PROCEDURE CONSTANT(FSYS: SETOFSYS; VAR FSP: STP; VAR FVALU: VALU); VAR LSP: STP; LCP: CTP; SIGN: (NONE,POS,NEG); LVP: CSP; BEGIN LSP := NIL; FVALU.IVAL := 0; IF NOT(SY IN CONSTBEGSYS) THEN BEGIN ERROR(50); SKIP(FSYS+CONSTBEGSYS) END; IF SY IN CONSTBEGSYS THEN BEGIN IF SY = STRINGCONSTSY THEN BEGIN IF LGTH = 1 THEN LSP := CHARPTR ELSE BEGIN NEW(LSP,ARRAYS,TRUE,TRUE); LSP^ := STRGPTR^; LSP^.MAXLENG := LGTH; LSP^.INXTYPE := NIL; NEW(LVP); LVP^ := VAL.VALP^; VAL.VALP := LVP END; FVALU := VAL; INSYMBOL END ELSE BEGIN SIGN := NONE; IF (SY = ADDOP) AND (OP IN [PLUS,MINUS]) THEN BEGIN IF OP = PLUS THEN SIGN := POS ELSE SIGN := NEG; INSYMBOL END; IF SY = IDENT THEN BEGIN SEARCHID([KONST],LCP); WITH LCP^ DO BEGIN LSP := IDTYPE; FVALU := VALUES END; IF SIGN <> NONE THEN IF LSP = INTPTR THEN BEGIN IF SIGN = NEG THEN FVALU.IVAL := -FVALU.IVAL END ELSE IF LSP = REALPTR THEN BEGIN IF SIGN = NEG THEN BEGIN NEW(LVP,REEL); LVP^.CCLASS := REEL; LVP^.RVAL := -FVALU.VALP^.RVAL; FVALU.VALP := LVP; END END ELSE ERROR(105); INSYMBOL; END ELSE IF SY = INTCONST THEN BEGIN IF SIGN = NEG THEN VAL.IVAL := -VAL.IVAL; LSP := INTPTR; FVALU := VAL; INSYMBOL END ELSE IF SY = REALCONST THEN BEGIN IF SIGN = NEG THEN VAL.VALP^.RVAL := -VAL.VALP^.RVAL; LSP := REALPTR; FVALU := VAL; INSYMBOL END ELSE BEGIN ERROR(106); SKIP(FSYS) END END; IF NOT (SY IN FSYS) THEN BEGIN ERROR(6); SKIP(FSYS) END END; FSP := LSP END (*CONSTANT*) ; FUNCTION COMPTYPES(FSP1,FSP2: STP) : BOOLEAN; VAR NXT1,NXT2: CTP; COMP: BOOLEAN; LTESTP1,LTESTP2 : TESTP; BEGIN IF FSP1 = FSP2 THEN COMPTYPES := TRUE ELSE IF (FSP1 = NIL) OR (FSP2 = NIL) THEN COMPTYPES := TRUE ELSE IF FSP1^.FORM = FSP2^.FORM THEN CASE FSP1^.FORM OF SCALAR: COMPTYPES := FALSE; SUBRANGE: COMPTYPES := COMPTYPES(FSP1^.RANGETYPE, FSP2^.RANGETYPE); POINTER: BEGIN COMP := FALSE; LTESTP1 := GLOBTESTP; LTESTP2 := GLOBTESTP; WHILE LTESTP1 <> NIL DO WITH LTESTP1^ DO BEGIN IF (ELT1 = FSP1^.ELTYPE) AND (ELT2 = FSP2^.ELTYPE) THEN COMP := TRUE; LTESTP1 := LASTTESTP END; IF NOT COMP THEN BEGIN NEW(LTESTP1); WITH LTESTP1^ DO BEGIN ELT1 := FSP1^.ELTYPE; ELT2 := FSP2^.ELTYPE; LASTTESTP := GLOBTESTP END; GLOBTESTP := LTESTP1; COMP := COMPTYPES(FSP1^.ELTYPE,FSP2^.ELTYPE) END; COMPTYPES := COMP; GLOBTESTP := LTESTP2 END; POWER: COMPTYPES := COMPTYPES(FSP1^.ELSET,FSP2^.ELSET); ARRAYS: BEGIN COMP := COMPTYPES(FSP1^.AELTYPE,FSP2^.AELTYPE) AND (FSP1^.AISPACKD = FSP2^.AISPACKD); IF COMP AND FSP1^.AISPACKD THEN COMP := (FSP1^.ELSPERWD = FSP2^.ELSPERWD) AND (FSP1^.ELWIDTH = FSP2^.ELWIDTH) AND (FSP1^.AISSTRNG = FSP2^.AISSTRNG); IF COMP AND NOT STRGTYPE(FSP1) THEN COMP := (FSP1^.SIZE = FSP2^.SIZE); COMPTYPES := COMP; END; RECORDS: BEGIN NXT1 := FSP1^.FSTFLD; NXT2 := FSP2^.FSTFLD; COMP := TRUE; WHILE (NXT1 <> NIL) AND (NXT2 <> NIL) AND COMP DO BEGIN COMP:=COMPTYPES(NXT1^.IDTYPE,NXT2^.IDTYPE); NXT1 := NXT1^.NEXT; NXT2 := NXT2^.NEXT END; COMPTYPES := COMP AND (NXT1 = NIL) AND (NXT2 = NIL) AND (FSP1^.RECVAR = NIL) AND (FSP2^.RECVAR = NIL) END; FILES: COMPTYPES := COMPTYPES(FSP1^.FILTYPE,FSP2^.FILTYPE) END (*CASE*) ELSE (*FSP1^.FORM <> FSP2^.FORM*) IF FSP1^.FORM = SUBRANGE THEN COMPTYPES := COMPTYPES(FSP1^.RANGETYPE,FSP2) ELSE IF FSP2^.FORM = SUBRANGE THEN COMPTYPES := COMPTYPES(FSP1,FSP2^.RANGETYPE) ELSE COMPTYPES := FALSE END (*COMPTYPES*) ; (*$I XCOMP:C.TEXT *) PROCEDURE TYP(FSYS: SETOFSYS; VAR FSP: STP; VAR FSIZE: ADDRRANGE); VAR LSP,LSP1,LSP2: STP; OLDTOP: DISPRANGE; LCP: CTP; LSIZE,DISPL: ADDRRANGE; LMIN,LMAX: INTEGER; PACKING: BOOLEAN; NEXTBIT,NUMBITS: BITRANGE; PROCEDURE SIMPLETYPE(FSYS:SETOFSYS; VAR FSP:STP; VAR FSIZE:ADDRRANGE); VAR LSP,LSP1: STP; LCP,LCP1: CTP; TTOP: DISPRANGE; LCNT: INTEGER; LVALU: VALU; BEGIN FSIZE := 1; IF NOT (SY IN SIMPTYPEBEGSYS) THEN BEGIN ERROR(1); SKIP(FSYS + SIMPTYPEBEGSYS) END; IF SY IN SIMPTYPEBEGSYS THEN BEGIN IF SY = LPARENT THEN BEGIN TTOP := TOP; WHILE DISPLAY[TOP].OCCUR <> BLCK DO TOP := TOP - 1; NEW(LSP,SCALAR,DECLARED); WITH LSP^ DO BEGIN SIZE := INTSIZE; FORM := SCALAR; SCALKIND := DECLARED END; LCP1 := NIL; LCNT := 0; REPEAT INSYMBOL; IF SY = IDENT THEN BEGIN NEW(LCP,KONST); WITH LCP^ DO BEGIN NAME := ID; IDTYPE := LSP; NEXT := LCP1; VALUES.IVAL := LCNT; KLASS := KONST END; ENTERID(LCP); LCNT := LCNT + 1; LCP1 := LCP; INSYMBOL END ELSE ERROR(2); IF NOT (SY IN FSYS + [COMMA,RPARENT]) THEN BEGIN ERROR(6); SKIP(FSYS + [COMMA,RPARENT]) END UNTIL SY <> COMMA; LSP^.FCONST := LCP1; TOP := TTOP; IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4) END ELSE BEGIN IF SY = IDENT THEN BEGIN SEARCHID([TYPES,KONST],LCP); INSYMBOL; IF LCP^.KLASS = KONST THEN BEGIN NEW(LSP,SUBRANGE); WITH LSP^, LCP^ DO BEGIN RANGETYPE := IDTYPE; FORM := SUBRANGE; IF STRGTYPE(RANGETYPE) THEN BEGIN ERROR(148); RANGETYPE := NIL END; MIN := VALUES; SIZE := INTSIZE END; IF SY = COLON THEN INSYMBOL ELSE ERROR(5); CONSTANT(FSYS,LSP1,LVALU); LSP^.MAX := LVALU; IF LSP^.RANGETYPE <> LSP1 THEN ERROR(107) END ELSE BEGIN LSP := LCP^.IDTYPE; IF (LSP = STRGPTR) AND (SY = LBRACK) THEN BEGIN INSYMBOL; CONSTANT(FSYS + [RBRACK],LSP1,LVALU); IF LSP1 = INTPTR THEN BEGIN IF (LVALU.IVAL <= 0) OR (LVALU.IVAL > STRGLGTH) THEN BEGIN ERROR(203); LVALU.IVAL := DEFSTRGLGTH END; IF LVALU.IVAL <> DEFSTRGLGTH THEN BEGIN NEW(LSP,ARRAYS,TRUE,TRUE); LSP^ := STRGPTR^; WITH LSP^,LVALU DO BEGIN MAXLENG := IVAL; SIZE := (IVAL+CHRSPERWD) DIV CHRSPERWD END END END ELSE ERROR(15); IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12) END; IF LSP <> NIL THEN FSIZE := LSP^.SIZE END END (*SY = IDENT*) ELSE BEGIN NEW(LSP,SUBRANGE); LSP^.FORM := SUBRANGE; CONSTANT(FSYS + [COLON],LSP1,LVALU); IF STRGTYPE(LSP1) THEN BEGIN ERROR(148); LSP1 := NIL END; WITH LSP^ DO BEGIN RANGETYPE:=LSP1; MIN:=LVALU; SIZE:=INTSIZE END; IF SY = COLON THEN INSYMBOL ELSE ERROR(5); CONSTANT(FSYS,LSP1,LVALU); LSP^.MAX := LVALU; IF LSP^.RANGETYPE <> LSP1 THEN ERROR(107) END; IF LSP <> NIL THEN WITH LSP^ DO IF FORM = SUBRANGE THEN IF RANGETYPE <> NIL THEN IF RANGETYPE = REALPTR THEN ERROR(399) ELSE IF MIN.IVAL > MAX.IVAL THEN BEGIN ERROR(102); MAX.IVAL := MIN.IVAL END END; FSP := LSP; IF NOT (SY IN FSYS) THEN BEGIN ERROR(6); SKIP(FSYS) END END ELSE FSP := NIL END (*SIMPLETYPE*) ; FUNCTION PACKABLE(FSP: STP): BOOLEAN; VAR LMIN,LMAX: INTEGER; BEGIN PACKABLE := FALSE; IF (FSP <> NIL) AND PACKING THEN WITH FSP^ DO CASE FORM OF SUBRANGE, SCALAR: IF (FSP <> INTPTR) AND (FSP <> REALPTR) THEN BEGIN GETBOUNDS(FSP,LMIN,LMAX); IF LMIN >= 0 THEN BEGIN PACKABLE := TRUE; NUMBITS := 1; LMIN := 1; WHILE LMIN < LMAX DO BEGIN LMIN := LMIN + 1; LMIN := LMIN + LMIN - 1; NUMBITS := NUMBITS + 1 END END END; POWER: IF PACKABLE(ELSET) THEN BEGIN GETBOUNDS(ELSET,LMIN,LMAX); LMAX := LMAX + 1; IF LMAX < BITSPERWD THEN BEGIN PACKABLE := TRUE; NUMBITS := LMAX END END END (* CASES *); END (*PACKABLE*) ; PROCEDURE FIELDLIST(FSYS: SETOFSYS; VAR FRECVAR: STP); VAR LCP,LCP1,NXT,NXT1,LAST: CTP; LSP,LSP1,LSP2,LSP3,LSP4: STP; MINSIZE,MAXSIZE,LSIZE: ADDRRANGE; LVALU: VALU; MAXBIT,MINBIT: BITRANGE; PROCEDURE ALLOCATE(FCP: CTP); VAR ONBOUND: BOOLEAN; BEGIN ONBOUND := FALSE; WITH FCP^ DO IF PACKABLE(IDTYPE) THEN BEGIN IF (NUMBITS + NEXTBIT) > BITSPERWD THEN BEGIN DISPL := DISPL + 1; NEXTBIT := 0; ONBOUND := TRUE END; FLDADDR := DISPL; FISPACKD := TRUE; FLDWIDTH := NUMBITS; FLDRBIT := NEXTBIT; NEXTBIT := NEXTBIT + NUMBITS END ELSE BEGIN DISPL := DISPL + ORD(NEXTBIT > 0); NEXTBIT := 0; ONBOUND := TRUE; FISPACKD := FALSE; FLDADDR := DISPL; IF IDTYPE <> NIL THEN DISPL := DISPL + IDTYPE^.SIZE END; IF ONBOUND AND (LAST <> NIL) THEN WITH LAST^ DO IF FISPACKD THEN IF FLDRBIT = 0 THEN FISPACKD := FALSE ELSE IF (FLDWIDTH <= 8) AND (FLDRBIT <= 8) THEN BEGIN FLDWIDTH := 8; FLDRBIT := 8 END END (*ALLOCATE*) ; PROCEDURE VARIANTLIST; VAR GOTTAGNAME: BOOLEAN; BEGIN NEW(LSP,TAGFLD); WITH LSP^ DO BEGIN TAGFIELDP := NIL; FSTVAR := NIL; FORM := TAGFLD END; FRECVAR := LSP; INSYMBOL; IF SY = IDENT THEN BEGIN IF PACKING THEN NEW(LCP,FIELD,TRUE) ELSE NEW(LCP,FIELD,FALSE); WITH LCP^ DO BEGIN IDTYPE := NIL; KLASS:=FIELD; NEXT := NIL; FISPACKD := FALSE END; GOTTAGNAME := FALSE; PRTERR := FALSE; SEARCHID([TYPES],LCP1); PRTERR := TRUE; IF LCP1 = NIL THEN BEGIN GOTTAGNAME := TRUE; LCP^.NAME := ID; ENTERID(LCP); INSYMBOL; IF SY = COLON THEN INSYMBOL ELSE ERROR(5) END; IF SY = IDENT THEN BEGIN SEARCHID([TYPES],LCP1); LSP1 := LCP1^.IDTYPE; IF LSP1 <> NIL THEN BEGIN IF LSP1^.FORM <= SUBRANGE THEN BEGIN IF COMPTYPES(REALPTR,LSP1) THEN ERROR(109); LCP^.IDTYPE := LSP1; LSP^.TAGFIELDP := LCP; IF GOTTAGNAME THEN ALLOCATE(LCP) END ELSE ERROR(110) END; INSYMBOL END ELSE BEGIN ERROR(2); SKIP(FSYS + [OFSY,LPARENT]) END END ELSE BEGIN ERROR(2); SKIP(FSYS + [OFSY,LPARENT]) END; LSP^.SIZE := DISPL + ORD(NEXTBIT > 0); IF SY = OFSY THEN INSYMBOL ELSE ERROR(8); LSP1 := NIL; MINSIZE := DISPL; MAXSIZE := DISPL; MINBIT := NEXTBIT; MAXBIT := NEXTBIT; REPEAT LSP2 := NIL; REPEAT CONSTANT(FSYS + [COMMA,COLON,LPARENT],LSP3,LVALU); IF LSP^.TAGFIELDP <> NIL THEN IF NOT COMPTYPES(LSP^.TAGFIELDP^.IDTYPE,LSP3) THEN ERROR(111); NEW(LSP3,VARIANT); WITH LSP3^ DO BEGIN NXTVAR := LSP1; SUBVAR := LSP2; VARVAL := LVALU; FORM := VARIANT END; LSP1 := LSP3; LSP2 := LSP3; TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = COLON THEN INSYMBOL ELSE ERROR(5); IF SY = LPARENT THEN INSYMBOL ELSE ERROR(9); IF SY = RPARENT THEN LSP2 := NIL ELSE FIELDLIST(FSYS + [RPARENT,SEMICOLON],LSP2); IF DISPL > MAXSIZE THEN BEGIN MAXSIZE := DISPL; MAXBIT := NEXTBIT END ELSE IF (DISPL = MAXSIZE) AND (NEXTBIT > MAXBIT) THEN MAXBIT := NEXTBIT; WHILE LSP3 <> NIL DO BEGIN LSP4 := LSP3^.SUBVAR; LSP3^.SUBVAR := LSP2; LSP3^.SIZE := DISPL + ORD(NEXTBIT > 0); LSP3 := LSP4 END; IF SY = RPARENT THEN BEGIN INSYMBOL; IF NOT (SY IN FSYS + [SEMICOLON]) THEN BEGIN ERROR(6); SKIP(FSYS + [SEMICOLON]) END END ELSE ERROR(4); TEST := SY <> SEMICOLON; IF NOT TEST THEN BEGIN INSYMBOL; DISPL := MINSIZE; NEXTBIT := MINBIT END UNTIL TEST; DISPL := MAXSIZE; NEXTBIT := MAXBIT; LSP^.FSTVAR := LSP1 END (*VARIANTLIST*) ; BEGIN (*FIELDLIST*) NXT1 := NIL; LSP := NIL; LAST := NIL; IF NOT (SY IN [IDENT,CASESY]) THEN BEGIN ERROR(19); SKIP(FSYS + [IDENT,CASESY]) END; WHILE SY = IDENT DO BEGIN NXT := NXT1; REPEAT IF SY = IDENT THEN BEGIN IF PACKING THEN NEW(LCP,FIELD,TRUE) ELSE NEW(LCP,FIELD,FALSE); WITH LCP^ DO BEGIN NAME := ID; IDTYPE := NIL; NEXT := NXT; KLASS := FIELD; FISPACKD := FALSE END; NXT := LCP; ENTERID(LCP); INSYMBOL END ELSE ERROR(2); IF NOT (SY IN [COMMA,COLON]) THEN BEGIN ERROR(6); SKIP(FSYS + [COMMA,COLON,SEMICOLON,CASESY]) END; TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = COLON THEN INSYMBOL ELSE ERROR(5); TYP(FSYS + [CASESY,SEMICOLON],LSP,LSIZE); IF LSP <> NIL THEN IF LSP^.FORM = FILES THEN ERROR(108); WHILE NXT <> NXT1 DO WITH NXT^ DO BEGIN IDTYPE := LSP; ALLOCATE(NXT); IF NEXT = NXT1 THEN LAST := NXT; NXT := NEXT END; NXT1 := LCP; IF SY = SEMICOLON THEN BEGIN INSYMBOL; IF NOT (SY IN [IDENT,CASESY]) THEN BEGIN ERROR(19); SKIP(FSYS + [IDENT,CASESY]) END END END (*WHILE*); NXT := NIL; WHILE NXT1 <> NIL DO WITH NXT1^ DO BEGIN LCP := NEXT; NEXT := NXT; NXT := NXT1; NXT1 := LCP END; IF SY = CASESY THEN VARIANTLIST ELSE FRECVAR := NIL END (*FIELDLIST*) ; PROCEDURE POINTERTYPE; BEGIN NEW(LSP,POINTER); FSP := LSP; WITH LSP^ DO BEGIN ELTYPE := NIL; SIZE := PTRSIZE; FORM := POINTER END; INSYMBOL; IF SY = IDENT THEN BEGIN PRTERR := FALSE; SEARCHID([TYPES],LCP); PRTERR := TRUE; IF LCP = NIL THEN (*FORWARD REFERENCED TYPE ID*) BEGIN NEW(LCP,TYPES); WITH LCP^ DO BEGIN NAME := ID; IDTYPE := LSP; NEXT := FWPTR; KLASS := TYPES END; FWPTR := LCP END ELSE BEGIN IF LCP^.IDTYPE <> NIL THEN IF (LCP^.IDTYPE^.FORM <> FILES) OR SYSCOMP THEN LSP^.ELTYPE := LCP^.IDTYPE ELSE ERROR(108) END; INSYMBOL; END ELSE ERROR(2) END (*POINTERTYPE*) ; BEGIN (*TYP*) PACKING := FALSE; IF NOT (SY IN TYPEBEGSYS) THEN BEGIN ERROR(10); SKIP(FSYS + TYPEBEGSYS) END; IF SY IN TYPEBEGSYS THEN BEGIN IF SY IN SIMPTYPEBEGSYS THEN SIMPLETYPE(FSYS,FSP,FSIZE) ELSE (*^*) IF SY = ARROW THEN POINTERTYPE ELSE BEGIN IF SY = PACKEDSY THEN BEGIN INSYMBOL; PACKING := TRUE; IF NOT (SY IN TYPEDELS) THEN BEGIN ERROR(10); SKIP(FSYS + TYPEDELS) END END; (*ARRAY*) IF SY = ARRAYSY THEN BEGIN INSYMBOL; IF SY = LBRACK THEN INSYMBOL ELSE ERROR(11); LSP1 := NIL; REPEAT IF PACKING THEN NEW(LSP,ARRAYS,TRUE,FALSE) ELSE NEW(LSP,ARRAYS,FALSE); WITH LSP^ DO BEGIN AELTYPE := LSP1; INXTYPE := NIL; IF PACKING THEN AISSTRNG := FALSE; AISPACKD := FALSE; FORM := ARRAYS END; LSP1 := LSP; SIMPLETYPE(FSYS + [COMMA,RBRACK,OFSY],LSP2,LSIZE); LSP1^.SIZE := LSIZE; IF LSP2 <> NIL THEN IF LSP2^.FORM <= SUBRANGE THEN BEGIN IF LSP2 = REALPTR THEN BEGIN ERROR(109); LSP2 := NIL END ELSE IF LSP2 = INTPTR THEN BEGIN ERROR(149); LSP2 := NIL END; LSP^.INXTYPE := LSP2 END ELSE BEGIN ERROR(113); LSP2 := NIL END; TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12); IF SY = OFSY THEN INSYMBOL ELSE ERROR(8); TYP(FSYS,LSP,LSIZE); IF LSP <> NIL THEN IF LSP^.FORM = FILES THEN ERROR(108); IF PACKABLE(LSP) THEN IF NUMBITS + NUMBITS <= BITSPERWD THEN WITH LSP1^ DO BEGIN AISPACKD := TRUE; ELSPERWD := BITSPERWD DIV NUMBITS; ELWIDTH := NUMBITS END; REPEAT WITH LSP1^ DO BEGIN LSP2 := AELTYPE; AELTYPE := LSP; IF INXTYPE <> NIL THEN BEGIN GETBOUNDS(INXTYPE,LMIN,LMAX); IF AISPACKD THEN LSIZE := (LMAX-LMIN+ELSPERWD) DIV ELSPERWD ELSE LSIZE := LSIZE*(LMAX - LMIN + 1); IF LSIZE <= 0 THEN BEGIN ERROR(398); LSIZE := 1 END; SIZE := LSIZE END END; LSP := LSP1; LSP1 := LSP2 UNTIL LSP1 = NIL END ELSE (*RECORD*) IF SY = RECORDSY THEN BEGIN INSYMBOL; OLDTOP := TOP; IF TOP < DISPLIMIT THEN BEGIN TOP := TOP + 1; WITH DISPLAY[TOP] DO BEGIN FNAME := NIL; OCCUR := REC END END ELSE ERROR(250); DISPL := 0; NEXTBIT := 0; FIELDLIST(FSYS-[SEMICOLON]+[ENDSY],LSP1); DISPL := DISPL + ORD(NEXTBIT > 0); NEW(LSP,RECORDS); WITH LSP^ DO BEGIN FSTFLD := DISPLAY[TOP].FNAME; RECVAR := LSP1; SIZE := DISPL; FORM := RECORDS END; TOP := OLDTOP; IF SY = ENDSY THEN INSYMBOL ELSE ERROR(13) END ELSE (*SET*) IF SY = SETSY THEN BEGIN INSYMBOL; IF SY = OFSY THEN INSYMBOL ELSE ERROR(8); SIMPLETYPE(FSYS,LSP1,LSIZE); IF LSP1 <> NIL THEN IF LSP1^.FORM > SUBRANGE BEGIN ERROR(115); LSP1 := NIL END ELSE IF LSP1 = REALPTR THEN BEGIN ERROR(114); LSP1 := NIL END; NEW(LSP,POWER); WITH LSP^ DO BEGIN ELSET := LSP1; FORM := POWER; IF LSP1 <> NIL THEN BEGIN GETBOUNDS(LSP1,LMIN,LMAX); SIZE := (LMAX + BITSPERWD) DIV BITSPERWD; END ELSE SIZE := 0 END END ELSE (*FILE*) IF SY = FILESY THEN BEGIN INSYMBOL; NEW(LSP,FILES); WITH LSP^ DO BEGIN FORM := FILES; FILTYPE := NIL END; IF SY = OFSY THEN BEGIN INSYMBOL; TYP(FSYS,LSP1,LSIZE) END ELSE LSP1 := NIL; LSP^.FILTYPE := LSP1; IF LSP1 <> NIL THEN LSP^.SIZE := FILESIZE + LSP1^.SIZE ELSE LSP^.SIZE := NILFILESIZE END; FSP := LSP END; IF NOT (SY IN FSYS) THEN BEGIN ERROR(6); SKIP(FSYS) END END ELSE FSP := NIL; IF FSP = NIL THEN FSIZE := 1 ELSE FSIZE := FSP^.SIZE END (*TYP*) ; PROCEDURE GENLDC(IVAL: INTEGER); FORWARD; PROCEDURE GENBYTE(FBYTE: INTEGER); BEGIN CODEP^[IC] := CHR(FBYTE); IC := IC+1 END (*GENBYTE*) ; PROCEDURE GENWORD(FWORD: INTEGER); BEGIN IF ODD(IC) THEN IC := IC + 1; MOVELEFT(FWORD,CODEP^[IC],2); IC := IC + 2 END (*GENWORD*) ; PROCEDURE GENBIG(IVAL: INTEGER); VAR LOWORDER: CHAR; BEGIN IF IVAL <= 127 THEN GENBYTE(IVAL) ELSE BEGIN MOVELEFT(IVAL,CODEP^[IC],2); LOWORDER := CODEP^[IC]; CODEP^[IC] := CHR(ORD(CODEP^[IC+1])+128); CODEP^[IC+1] := LOWORDER; IC := IC+2 END END (*GENBIG*) ; PROCEDURE GEN0(FOP: OPRANGE); VAR I: INTEGER; BEGIN GENBYTE(FOP+128); IF FOP = 38(*LCA*) THEN WITH GATTR.CVAL.VALP^ DO BEGIN GENBYTE(SLGTH); FOR I := 1 TO SLGTH DO GENBYTE(ORD(SVAL[I])) END END (*GEN0*) ; PROCEDURE GEN1(FOP: OPRANGE; FP2: INTEGER); LABEL 1; VAR I,J: INTEGER; BEGIN GENBYTE(FOP+128); IF FOP = 51(*LDC*) THEN BEGIN IF FP2 = 2 THEN I := REALSIZE ELSE BEGIN I := 8; WHILE I > 0 DO IF GATTR.CVAL.VALP^.CSTVAL[I] <> 0 THEN GOTO 1 ELSE I := I - 1; 1: END; GATTR.TYPTR^.SIZE := I; IF I > 1 THEN BEGIN GENBYTE(I); FOR J := I DOWNTO 1 DO GENWORD(GATTR.CVAL.VALP^.CSTVAL[J]) END ELSE BEGIN IC := IC - 1; IF I = 1 THEN GENLDC(GATTR.CVAL.VALP^.CSTVAL[1]) END END ELSE IF FOP IN [30(*CSP*),32(*ADJ*),45(*RNP*), 46(*CIP*),60(*LDM*),61(*STM*), 65(*RBP*),66(*CBP*),78(*CLP*), 42(*SAS*),79(*CGP*)] THEN GENBYTE(FP2) ELSE IF ((FOP = 74(*LDL*)) OR (FOP = 39(*LDO*))) AND (FP2 <= 16) THEN BEGIN IC := IC-1; IF FOP = 39(*LDO*) THEN GENBYTE(231+FP2) ELSE GENBYTE(215+FP2) END ELSE IF (FOP = 35(*IND*)) AND (FP2 <= 7) THEN BEGIN IC := IC-1; GENBYTE(248+FP2) END ELSE GENBIG(FP2) END (*GEN1*) ; PROCEDURE GEN2(FOP: OPRANGE; FP1,FP2: INTEGER); BEGIN IF (FOP = 64(*IXP*)) OR (FOP = 77(*CXP*)) THEN BEGIN GENBYTE(FOP+128); GENBYTE(FP1); GENBYTE(FP2); END ELSE IF FOP IN [47(*EQU*),48(*GEQ*),49(*GRT*), 52(*LEQ*),53(*LES*),55(*NEQ*)] THEN IF FP1 = 0 THEN GEN0(FOP+20) ELSE BEGIN GEN1(FOP,FP1+FP1); IF FP1 > 4 THEN GENBIG(FP2) END ELSE BEGIN (*LDA,LOD,STR*) IF FP1 = 0 THEN GEN1(FOP+20,FP2) ELSE BEGIN GENBYTE(FOP+128); GENBYTE(FP1); GENBIG(FP2) END END; END (*GEN2*) ; PROCEDURE GENLDC; BEGIN IF (IVAL >= 0) AND (IVAL <= 127) THEN GENBYTE(IVAL) ELSE BEGIN GENBYTE(51(*LDC*)+148); MOVELEFT(IVAL,CODEP^[IC],2); IC := IC+2 END END (*GENLDC*) ; PROCEDURE GENJMP(FOP: OPRANGE; FLBP: LBP); VAR DISP: INTEGER; BEGIN WITH FLBP^ DO IF DEFINED THEN BEGIN GENBYTE(FOP+128); DISP := OCCURIC-IC-1; IF (DISP >= 0) AND (DISP <= 127) THEN GENBYTE(DISP) ELSE BEGIN IF JTABINX = 0 THEN BEGIN JTABINX := NEXTJTAB; IF NEXTJTAB = MAXJTAB THEN ERROR(253) ELSE NEXTJTAB := NEXTJTAB + 1; JTAB[JTABINX] := OCCURIC END; DISP := -JTABINX; GENBYTE(248-JTABINX-JTABINX) END; END ELSE BEGIN MOVELEFT(REFLIST,CODEP^[IC],2); IF FOP = 57(*UJP*) THEN DISP := IC + 4096 ELSE DISP := IC; REFLIST := DISP; IC := IC+2 END; END (*GENJMP*) ; PROCEDURE LOAD; FORWARD; PROCEDURE GENFJP(FLBP: LBP); BEGIN LOAD; IF GATTR.TYPTR <> BOOLPTR THEN ERROR(135); GENJMP(33(*FJP*),FLBP) END (*GENFJP*) ; PROCEDURE GENLABEL(VAR FLBP: LBP); BEGIN NEW(FLBP); WITH FLBP^ DO BEGIN DEFINED := FALSE; REFLIST := MAXADDR END END (*GENLABEL*) ; PROCEDURE PUTLABEL(FLBP: LBP); VAR LREF: INTEGER; LOP: OPRANGE; BEGIN WITH FLBP^ DO BEGIN LREF := REFLIST; DEFINED := TRUE; OCCURIC := IC; JTABINX := 0; WHILE LREF < MAXADDR DO BEGIN IF LREF >= 4096 THEN BEGIN LREF := LREF - 4096; LOP := 57(*UJP*) END ELSE LOP := 33(*FJP*); IC := LREF; MOVELEFT(CODEP^[IC],LREF,2); GENJMP(LOP,FLBP) END; IC := OCCURIC END END (*PUTLABEL*) ; PROCEDURE LOAD; BEGIN WITH GATTR DO IF TYPTR <> NIL THEN BEGIN CASE KIND OF CST: IF (TYPTR^.FORM = SCALAR) AND (TYPTR <> REALPTR) THEN GENLDC(CVAL.IVAL) ELSE IF TYPTR = NILPTR THEN GEN0(31(*LDCN*)) ELSE IF TYPTR = REALPTR THEN GEN1(51(*LDC*),2) ELSE GEN1(51(*LDC*),5); VARBL: CASE ACCESS OF DRCT: IF VLEVEL = 1 THEN GEN1(39(*LDO*),DPLMT) ELSE GEN2(54(*LOD*),LEVEL-VLEVEL,DPLMT); INDRCT: GEN1(35(*IND*),IDPLMT); PACKD: GEN0(58(*LDP*)); MULTI: GEN1(60(*LDM*),TYPTR^.SIZE); BYTE: GEN0(62(*LDB*)) END; EXPR: END; IF (TYPTR^.FORM = POWER) AND (KIND <> EXPR) THEN GENLDC(TYPTR^.SIZE); KIND := EXPR END END (*LOAD*) ; PROCEDURE STORE(VAR FATTR: ATTR); BEGIN WITH FATTR DO IF TYPTR <> NIL THEN CASE ACCESS OF DRCT: IF VLEVEL = 1 THEN GEN1(43(*SRO*),DPLMT) ELSE GEN2(56(*STR*),LEVEL-VLEVEL,DPLMT); INDRCT: IF IDPLMT <> 0 THEN ERROR(400) ELSE GEN0(26(*STO*)); PACKD: GEN0(59(*STP*)); MULTI: GEN1(61(*STM*),TYPTR^.SIZE); BYTE: GEN0(63(*STB*)) END END (*STORE*) ; PROCEDURE LOADADDRESS; BEGIN WITH GATTR DO IF TYPTR <> NIL THEN BEGIN CASE KIND OF CST: IF STRGTYPE(TYPTR) THEN GEN0(38(*LCA*)) ELSE ERROR(400); VARBL: CASE ACCESS OF DRCT: IF VLEVEL = 1 THEN GEN1(37(*LAO*),DPLMT) ELSE GEN2(50(*LDA*),LEVEL-VLEVEL,DPLMT); INDRCT: IF IDPLMT <> 0 THEN GEN1(34(*INC*),IDPLMT+IDPLMT); PACKD: ERROR(103) END END; KIND := VARBL; ACCESS := INDRCT; IDPLMT := 0 END END (*LOADADDRESS*) ; PROCEDURE WRITECODE(FORCEBUF: BOOLEAN); VAR CODEINX,LIC,I: INTEGER; BEGIN CODEINX := 0; LIC := IC; REPEAT I := 512-CURBYTE; IF I > LIC THEN I := LIC; MOVELEFT(CODEP^[CODEINX],DISKBUF[CURBYTE],I); CODEINX := CODEINX+I; CURBYTE := CURBYTE+I; IF (CURBYTE = 512) OR FORCEBUF THEN BEGIN IF BLOCKWRITE(USERINFO.WORKCODE^,DISKBUF,1,CURBLK) <> 1 THEN ERROR(402); CURBLK := CURBLK+1; CURBYTE := 0 END; LIC := LIC-I UNTIL LIC = 0; END (*WRITECODE*) ; PROCEDURE FINISHSEG; VAR I: INTEGER; BEGIN IC := 0; FOR I := NEXTPROC-1 DOWNTO 1 DO GENWORD(SEGINX+IC-PROCTABLE[I]); GENBYTE(SEG); GENBYTE(NEXTPROC-1); SEGTABLE[SEG].CODELENG := SEGINX+IC; WRITECODE(TRUE); SEGINX := 0; CODEINSEG := FALSE END (*FINISHSEG*) ; (*$I XCOMP:D.TEXT *) PROCEDURE EXPRESSION(FSYS: SETOFSYS); FORWARD; PROCEDURE SELECTOR(FSYS: SETOFSYS; FCP: CTP); VAR LATTR: ATTR; LCP: CTP; LMIN,LMAX: INTEGER; BEGIN WITH FCP^, GATTR DO BEGIN TYPTR := IDTYPE; KIND := VARBL; CASE KLASS OF VARS: IF VKIND = ACTUAL THEN BEGIN ACCESS := DRCT; VLEVEL := VLEV; DPLMT := VADDR END ELSE BEGIN IF VLEV = 1 THEN GEN1(39(*LDO*),VADDR) ELSE GEN2(54(*LOD*),LEVEL-VLEV,VADDR); ACCESS := INDRCT; IDPLMT := 0 END; FIELD: WITH DISPLAY[DISX] DO BEGIN IF OCCUR = CREC THEN BEGIN ACCESS := DRCT; VLEVEL := CLEV; DPLMT := CDSPL + FLDADDR END ELSE BEGIN IF LEVEL = 1 THEN GEN1(39(*LDO*),VDSPL) ELSE GEN2(54(*LOD*),0,VDSPL); ACCESS := INDRCT; IDPLMT := FLDADDR END; IF FISPACKD THEN BEGIN LOADADDRESS; IF ((FLDRBIT = 0) OR (FLDRBIT = 8)) AND (FLDWIDTH = 8) THEN BEGIN ACCESS := BYTE; IF FLDRBIT = 8 THEN GEN1(34(*INC*),1) END ELSE BEGIN ACCESS := PACKD; GENLDC(FLDWIDTH); GENLDC(FLDRBIT) END END END; FUNC: IF PFDECKIND <> DECLARED THEN ERROR(150) ELSE IF NOT INSCOPE THEN ERROR(103) ELSE BEGIN ACCESS := DRCT; VLEVEL := PFLEV + 1; DPLMT := LCAFTERMARKSTACK END END (*CASE*); IF TYPTR <> NIL THEN IF (TYPTR^.FORM <= POWER) AND (TYPTR^.SIZE > PTRSIZE) THEN BEGIN LOADADDRESS; ACCESS := MULTI END END (*WITH*); IF NOT (SY IN SELECTSYS + FSYS) THEN BEGIN ERROR(59); SKIP(SELECTSYS + FSYS) END; WHILE SY IN SELECTSYS DO BEGIN (*[*) IF SY = LBRACK THEN BEGIN REPEAT LATTR := GATTR; WITH LATTR DO IF TYPTR <> NIL THEN IF TYPTR^.FORM <> ARRAYS THEN BEGIN ERROR(138); TYPTR := NIL END; LOADADDRESS; INSYMBOL; EXPRESSION(FSYS + [COMMA,RBRACK]); LOAD; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <> SCALAR THEN ERROR(113); IF LATTR.TYPTR <> NIL THEN WITH LATTR.TYPTR^ DO BEGIN IF COMPTYPES(INXTYPE,GATTR.TYPTR) THEN BEGIN IF (INXTYPE <> NIL) AND NOT STRGTYPE(LATTR.TYPTR) THEN BEGIN GETBOUNDS(INXTYPE,LMIN,LMAX); IF RANGECHECK THEN BEGIN GENLDC(LMIN); GENLDC(LMAX); GEN0(8(*CHK*)) END; IF LMIN <> 0 THEN BEGIN GENLDC(ABS(LMIN)); IF LMIN > 0 THEN GEN0(21(*SBI*)) ELSE GEN0(2(*ADI*)) END END END ELSE ERROR(139); WITH GATTR DO BEGIN TYPTR := AELTYPE; KIND := VARBL; ACCESS := INDRCT; IDPLMT := 0; IF TYPTR <> NIL THEN IF AISPACKD THEN IF ELWIDTH = 8 THEN BEGIN ACCESS := BYTE; IF STRGTYPE(LATTR.TYPTR) AND RANGECHECK THEN GEN0(27(*IXS*)) ELSE GEN0(2(*ADI*)) END ELSE BEGIN ACCESS := PACKD; GEN2(64(*IXP*),ELSPERWD,ELWIDTH) END ELSE BEGIN GEN1(36(*IXA*),TYPTR^.SIZE); IF (TYPTR^.FORM <= POWER) AND (TYPTR^.SIZE > PTRSIZE) THEN ACCESS := MULTI END END END UNTIL SY <> COMMA; IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12) END (*IF SY = LBRACK*) ELSE (*.*) IF SY = PERIOD THEN BEGIN WITH GATTR DO BEGIN IF TYPTR <> NIL THEN IF TYPTR^.FORM <> RECORDS THEN BEGIN ERROR(140); TYPTR := NIL END; INSYMBOL; IF SY = IDENT THEN BEGIN IF TYPTR <> NIL THEN BEGIN SEARCHSECTION(TYPTR^.FSTFLD,LCP); IF LCP = NIL THEN BEGIN ERROR(152); TYPTR := NIL END ELSE WITH LCP^ DO BEGIN TYPTR := IDTYPE; CASE ACCESS OF DRCT: DPLMT := DPLMT + FLDADDR; INDRCT: IDPLMT := IDPLMT + FLDADDR; MULTI,BYTE, PACKD: ERROR(400) END (*CASE ACCESS*); IF FISPACKD THEN BEGIN LOADADDRESS; IF ((FLDRBIT = 0) OR (FLDRBIT = 8)) AND (FLDWIDTH = 8) THEN BEGIN ACCESS := BYTE; IF FLDRBIT = 8 THEN GEN1(34(*INC*),1) END ELSE BEGIN ACCESS := PACKD; GENLDC(FLDWIDTH); GENLDC(FLDRBIT) END END; IF TYPTR <> NIL THEN IF (TYPTR^.FORM <= POWER) AND (TYPTR^.SIZE > PTRSIZE) THEN BEGIN LOADADDRESS; ACCESS := MULTI END END END; INSYMBOL END (*SY = IDENT*) ELSE ERROR(2) END (*WITH GATTR*) END (*IF SY = PERIOD*) ELSE (*^*) BEGIN IF GATTR.TYPTR <> NIL THEN WITH GATTR,TYPTR^ DO IF (FORM = POINTER) OR (FORM = FILES) THEN BEGIN LOAD; KIND := VARBL; ACCESS := INDRCT; IDPLMT := 0; IF FORM = POINTER THEN TYPTR := ELTYPE ELSE BEGIN TYPTR := FILTYPE; IF TYPTR = NIL THEN ERROR(399) END; IF TYPTR <> NIL THEN IF (TYPTR^.FORM <= POWER) AND (TYPTR^.SIZE > PTRSIZE) THEN ACCESS := MULTI END ELSE ERROR(141); INSYMBOL END; IF NOT (SY IN FSYS + SELECTSYS) THEN BEGIN ERROR(6); SKIP(FSYS + SELECTSYS) END END (*WHILE*) END (*SELECTOR*) ; PROCEDURE CALL(FSYS: SETOFSYS; FCP: CTP); VAR LKEY: 1..40; WASLPARENT: BOOLEAN; PROCEDURE VARIABLE(FSYS: SETOFSYS); VAR LCP: CTP; BEGIN IF SY = IDENT THEN BEGIN SEARCHID([FIELD,VARS],LCP); INSYMBOL END ELSE BEGIN ERROR(2); LCP := UVARPTR END; SELECTOR(FSYS,LCP) END (*VARIABLE*) ; PROCEDURE STRGVAR(FSYS: SETOFSYS; MUSTBEVAR: BOOLEAN); BEGIN EXPRESSION(FSYS); WITH GATTR DO IF ((KIND = CST) AND (TYPTR = CHARPTR)) OR STRGTYPE(TYPTR) THEN IF KIND = VARBL THEN LOADADDRESS ELSE BEGIN IF MUSTBEVAR THEN ERROR(154); IF KIND = CST THEN BEGIN IF TYPTR = CHARPTR THEN BEGIN WITH SCONST^ DO BEGIN CCLASS := STRG; SLGTH := 1; SVAL[1] := CHR(CVAL.IVAL) END; CVAL.VALP := SCONST; NEW(TYPTR,ARRAYS,TRUE,TRUE); TYPTR^ := STRGPTR^; TYPTR^.MAXLENG := 1 END; LOADADDRESS END END ELSE BEGIN IF GATTR.TYPTR <> NIL THEN ERROR(125); GATTR.TYPTR := STRGPTR END END (*STRGVAR*) ; PROCEDURE NEWSTMT; LABEL 1; VAR LSP,LSP1: STP; VARTS,LMIN,LMAX: INTEGER; LSIZE,LSZ: ADDRRANGE; LVAL: VALU; BEGIN VARIABLE(FSYS + [COMMA,RPARENT]); LOADADDRESS; LSP := NIL; VARTS := 0; LSIZE := 0; IF GATTR.TYPTR <> NIL THEN WITH GATTR.TYPTR^ DO IF FORM = POINTER THEN BEGIN IF ELTYPE <> NIL THEN WITH ELTYPE^ DO BEGIN LSIZE := SIZE; IF FORM = RECORDS THEN LSP := RECVAR END END ELSE ERROR(116); WHILE SY = COMMA DO BEGIN INSYMBOL; CONSTANT(FSYS + [COMMA,RPARENT],LSP1,LVAL); VARTS := VARTS + 1; IF LSP = NIL THEN ERROR(158) ELSE IF LSP^.FORM <> TAGFLD THEN ERROR(162) ELSE IF LSP^.TAGFIELDP <> NIL THEN IF STRGTYPE(LSP1) OR (LSP1 = REALPTR) THEN ERROR(159) ELSE IF COMPTYPES(LSP^.TAGFIELDP^.IDTYPE,LSP1) THEN BEGIN LSP1 := LSP^.FSTVAR; WHILE LSP1 <> NIL DO WITH LSP1^ DO IF VARVAL.IVAL = LVAL.IVAL THEN BEGIN LSIZE := SIZE; LSP := SUBVAR; GOTO 1 END ELSE LSP1 := NXTVAR; LSIZE := LSP^.SIZE; LSP := NIL; END ELSE ERROR(116); 1: END (*WHILE*) ; GENLDC(LSIZE); GEN1(30(*CSP*),1(*NEW*)) END (*NEWSTMT*) ; PROCEDURE MOVE; BEGIN VARIABLE(FSYS + [COMMA]); LOADADDRESS; IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); IF LKEY = 27 THEN BEGIN EXPRESSION(FSYS + [COMMA]); LOAD END ELSE BEGIN VARIABLE(FSYS + [COMMA]); LOADADDRESS END; IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); EXPRESSION(FSYS + [RPARENT]); LOAD; IF LKEY = 27 THEN GEN1(30(*CSP*),10(*FLC*)) ELSE IF LKEY = 21 THEN GEN1(30(*CSP*),2(*MVL*)) ELSE GEN1(30(*CSP*),3(*MVR*)) END (*MOVE*) ; PROCEDURE EXIT; VAR LCP: CTP; BEGIN IF SY = IDENT THEN BEGIN SEARCHID([PROC,FUNC],LCP); INSYMBOL END ELSE IF (SY = PROGSY) THEN BEGIN LCP := OUTERBLOCK; INSYMBOL END ELSE LCP := NIL; IF LCP <> NIL THEN IF LCP^.PFDECKIND = DECLARED THEN BEGIN GENLDC(LCP^.PFSEG); GENLDC(LCP^.PFNAME) END ELSE ERROR(125) ELSE ERROR(125); GEN1(30(*CSP*),4(*XIT*)) END (*EXIT*) ; PROCEDURE UNITIO; BEGIN IF GATTR.TYPTR <> INTPTR THEN ERROR(125); IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); VARIABLE(FSYS + [COMMA]); LOADADDRESS; IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); EXPRESSION(FSYS + [COMMA,RPARENT]); LOAD; IF GATTR.TYPTR <> INTPTR THEN ERROR(125); IF SY = COMMA THEN BEGIN INSYMBOL; IF SY = COMMA THEN GENLDC(0) ELSE BEGIN EXPRESSION(FSYS + [COMMA,RPARENT]); LOAD; IF GATTR.TYPTR <> INTPTR THEN ERROR(125) END END ELSE GENLDC(0); IF SY = COMMA THEN BEGIN INSYMBOL; EXPRESSION(FSYS + [RPARENT]); LOAD; IF GATTR.TYPTR <> INTPTR THEN ERROR(125) END ELSE GENLDC(0); IF LKEY = 13 THEN GEN1(30(*CSP*),5(*URD*)) ELSE GEN1(30(*CSP*),6(*UWT*)) END (*UNITIO*); PROCEDURE CONCAT; VAR LLC: ADDRRANGE; TEMPLGTH: INTEGER; BEGIN TEMPLGTH := 0; LLC := LC; LC := LC + (STRGLGTH DIV CHRSPERWD) + 1; GENLDC(0); GEN2(56(*STR*),0,LLC); GEN2(50(*LDA*),0,LLC); REPEAT STRGVAR(FSYS + [COMMA,RPARENT],FALSE); TEMPLGTH := TEMPLGTH + GATTR.TYPTR^.MAXLENG; IF TEMPLGTH < STRGLGTH THEN GENLDC(TEMPLGTH) ELSE GENLDC(STRGLGTH); GEN2(77(*CXP*),0(*SYS*),23(*SCONCAT*)); GEN2(50(*LDA*),0,LLC); TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF TEMPLGTH < STRGLGTH THEN LC := LLC + (TEMPLGTH DIV CHRSPERWD) + 1 ELSE TEMPLGTH := STRGLGTH; IF LC > LCMAX THEN LCMAX := LC; LC := LLC; WITH GATTR DO BEGIN NEW(TYPTR,ARRAYS,TRUE,TRUE); TYPTR^ := STRGPTR^; TYPTR^.MAXLENG := TEMPLGTH END END (*CONCAT*) ; PROCEDURE COPYDELETE; VAR LLC: ADDRRANGE; LSP: STP; BEGIN IF LKEY = 19 THEN BEGIN LLC := LC; LC := LC + (STRGLGTH DIV CHRSPERWD) + 1; END; STRGVAR(FSYS + [COMMA], LKEY = 18); IF LKEY = 19 THEN BEGIN LSP := GATTR.TYPTR; GEN2(50(*LDA*),0,LLC) END; IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); EXPRESSION(FSYS + [COMMA]); LOAD; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR <> INTPTR THEN ERROR(125); IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); EXPRESSION(FSYS + [RPARENT]); LOAD; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR <> INTPTR THEN ERROR(125); IF LKEY = 19 THEN BEGIN GEN2(77(*CXP*),0(*SYS*),25(*SCOPY*)); GEN2(50(*LDA*),0,LLC); IF LSP^.MAXLENG < STRGLGTH THEN LC := LLC + (LSP^.MAXLENG DIV CHRSPERWD) + 1; IF LC > LCMAX THEN LCMAX := LC; LC := LLC; GATTR.TYPTR := LSP END ELSE GEN2(77(*CXP*),0(*SYS*),26(*SDELETE*)) END (*COPYDELETE*) ; PROCEDURE CLOSE; BEGIN VARIABLE(FSYS + [COMMA,RPARENT]); LOADADDRESS; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <> FILES THEN ERROR(125); IF SY = COMMA THEN BEGIN INSYMBOL; IF SY = IDENT THEN BEGIN IF ID = 'NORMAL ' THEN GENLDC(0) ELSE IF ID = 'LOCK ' THEN GENLDC(1) ELSE IF ID = 'PURGE ' THEN GENLDC(2) ELSE IF ID = 'CRUNCH ' THEN GENLDC(3) ELSE ERROR(2); INSYMBOL END ELSE ERROR(2) END ELSE GENLDC(0); GEN2(77(*CXP*),0(*SYS*),6(*FCLOSE*)); IF IOCHECK THEN GEN1(30(*CSP*),0(*IOC*)) END (*CLOSE*) ; PROCEDURE GETPUTETC; BEGIN VARIABLE(FSYS + [COMMA,RPARENT]); LOADADDRESS; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <> FILES THEN ERROR(125) CASE LKEY OF 32: BEGIN IF SY = COMMA THEN BEGIN INSYMBOL; EXPRESSION(FSYS + [RPARENT]); LOAD; IF GATTR.TYPTR <> INTPTR THEN ERROR(125) END ELSE ERROR(125); GEN2(77(*CXP*),0(*SYS*),9(*FSEEK*)) END; 33: GEN2(77(*CXP*),0(*SYS*),4(*FRESET*)); 34: GEN2(77(*CXP*),0(*SYS*),7(*FGET*)); 35: GEN2(77(*CXP*),0(*SYS*),8(*FPUT*)); 40: BEGIN IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FILTYPE <> CHARPTR THEN ERROR(399); GENLDC(12); GENLDC(0); GEN2(77(*CXP*),0(*SYS*),17(*WRC*)) END END (*CASE*) ; IF IOCHECK THEN GEN1(30(*CSP*),0(*IOC*)) END (*GETPUTETC*) ; PROCEDURE SCAN; BEGIN IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR <> INTPTR THEN ERROR(125); IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); IF SY = RELOP THEN BEGIN IF OP = EQOP THEN GENLDC(0) ELSE IF OP = NEOP THEN GENLDC(1) ELSE ERROR(125); INSYMBOL END ELSE ERROR(125); EXPRESSION(FSYS + [COMMA]); LOAD; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR <> CHARPTR THEN ERROR(125); IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); VARIABLE(FSYS + [COMMA,RPARENT]); LOADADDRESS; IF SY = COMMA THEN BEGIN INSYMBOL; EXPRESSION(FSYS + [RPARENT]); LOAD END ELSE GENLDC(0); GEN1(30(*CSP*),11(*SCN*)); GATTR.TYPTR := INTPTR END (*SCAN*) ; PROCEDURE BLOCKIO; BEGIN VARIABLE(FSYS + [COMMA]); LOADADDRESS; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <> FILES THEN ERROR(125) ELSE IF GATTR.TYPTR^.FILTYPE <> NIL THEN ERROR(399); IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); VARIABLE(FSYS + [COMMA]); LOADADDRESS; IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); EXPRESSION(FSYS + [COMMA,RPARENT]); LOAD; IF GATTR.TYPTR <> INTPTR THEN ERROR(125); IF SY = COMMA THEN BEGIN INSYMBOL; EXPRESSION(FSYS + [RPARENT]); LOAD; IF GATTR.TYPTR <> INTPTR THEN ERROR(125) END ELSE GENLDC(-1); IF LKEY = 37 THEN GENLDC(1) ELSE GENLDC(0); GENLDC(0); GENLDC(0); GEN2(77(*CXP*),0(*SYS*),28(*BLOCKIO*)); IF IOCHECK THEN GEN1(30(*CSP*),0(*IOC*)); GATTR.TYPTR := INTPTR END (*BLOCKIO*) ; PROCEDURE DRAWSTUFF; VAR I,N: INTEGER; BEGIN VARIABLE(FSYS + [COMMA]); LOADADDRESS; IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); VARIABLE(FSYS + [COMMA]); LOADADDRESS; IF LKEY = 42 THEN N := 6 ELSE N := 5; FOR I := 0 TO N DO BEGIN IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); EXPRESSION(FSYS + [COMMA,RPARENT]); LOAD; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR <> INTPTR THEN ERROR(125) END; IF LKEY = 42 THEN N := 13 ELSE N := 12; GEN1(30(*CSP*),N) END (*DRAWSTUFF*) ; PROCEDURE SIZEOF; VAR LCP: CTP; BEGIN IF SY = IDENT THEN BEGIN SEARCHID([TYPES,VARS,FIELD],LCP); INSYMBOL; IF LCP^.IDTYPE <> NIL THEN GENLDC(LCP^.IDTYPE^.SIZE*CHRSPERWD) END; GATTR.TYPTR := INTPTR END (*SIZEOF*) ; PROCEDURE LOADIDADDR(FCP: CTP); BEGIN WITH FCP^ DO IF VKIND = ACTUAL THEN IF VLEV = 1 THEN GEN1(37(*LAO*),VADDR) ELSE GEN2(50(*LDA*),LEVEL-VLEV,VADDR) ELSE IF VLEV = 1 THEN GEN1(39(*LDO*),VADDR) ELSE GEN2(54(*LOD*),LEVEL-VLEV,VADDR) END (*LOADIDADDR*) ; PROCEDURE READ; VAR FILEPTR,LCP: CTP; BEGIN FILEPTR := INPUTPTR; IF (SY = IDENT) AND WASLPARENT THEN BEGIN SEARCHID([FIELD,VARS],LCP); IF LCP^.IDTYPE <> NIL THEN IF LCP^.IDTYPE^.FORM = FILES THEN IF LCP^.IDTYPE^.FILTYPE = CHARPTR THEN BEGIN INSYMBOL; FILEPTR := LCP; IF NOT (SY IN [COMMA,RPARENT]) THEN ERROR(20); IF SY = COMMA THEN INSYMBOL END END ELSE IF WASLPARENT THEN ERROR(2); IF WASLPARENT AND (SY <> RPARENT) THEN BEGIN REPEAT LOADIDADDR(FILEPTR); VARIABLE(FSYS + [COMMA,RPARENT]); LOADADDRESS; IF GATTR.TYPTR <> NIL THEN IF COMPTYPES(INTPTR,GATTR.TYPTR) THEN GEN2(77(*CXP*),0(*SYS*),12(*FRDI*)) ELSE IF COMPTYPES(REALPTR,GATTR.TYPTR) THEN GEN2(77(*CXP*),0(*SYS*),14(*FRDR*)) ELSE IF COMPTYPES(CHARPTR,GATTR.TYPTR) THEN GEN2(77(*CXP*),0(*SYS*),16(*FRDC*)) ELSE IF STRGTYPE(GATTR.TYPTR) THEN BEGIN GENLDC(GATTR.TYPTR^.MAXLENG); GEN2(77(*CXP*),0(*SYS*),18(*FRDS*)) END ELSE ERROR(125); IF IOCHECK THEN GEN1(30(*CSP*),0(*IOC*)); TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST END; IF LKEY = 2 THEN BEGIN LOADIDADDR(FILEPTR); GEN2(77(*CXP*),0(*SYS*),21(*FRLN*)); IF IOCHECK THEN GEN1(30(*CSP*),0(*IOC*)) END END (*READ*) ; PROCEDURE WRITE; VAR LSP: STP; DEFAULT: BOOLEAN; FILEPTR,LCP: CTP; LEN,LMIN,LMAX: INTEGER; BEGIN FILEPTR := OUTPUTPTR; IF (SY = IDENT) AND WASLPARENT THEN BEGIN SEARCHID([FIELD,VARS,KONST,FUNC],LCP); IF LCP^.IDTYPE <> NIL THEN IF LCP^.IDTYPE^.FORM = FILES THEN IF LCP^.IDTYPE^.FILTYPE = CHARPTR THEN BEGIN INSYMBOL; FILEPTR := LCP; IF NOT (SY IN [COMMA,RPARENT]) THEN ERROR(20); IF SY = COMMA THEN INSYMBOL END END; IF (SY IN FACBEGSYS) AND WASLPARENT THEN BEGIN REPEAT LOADIDADDR(FILEPTR); EXPRESSION(FSYS + [COMMA,COLON,RPARENT]); LSP := GATTR.TYPTR; IF LSP <> NIL THEN IF LSP^.FORM <= SUBRANGE THEN LOAD ELSE LOADADDRESS; IF SY = COLON THEN BEGIN INSYMBOL; EXPRESSION(FSYS + [COMMA,COLON,RPARENT]); IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR <> INTPTR THEN ERROR(20); LOAD; DEFAULT := FALSE END ELSE DEFAULT := TRUE; IF LSP = INTPTR THEN BEGIN IF DEFAULT THEN GENLDC(0); GEN2(77(*CXP*),0(*SYS*),13(*FWRI*)) END ELSE IF LSP = REALPTR THEN BEGIN IF DEFAULT THEN GENLDC(0); IF SY = COLON THEN BEGIN INSYMBOL; EXPRESSION(FSYS + [COMMA,RPARENT]); LOAD; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR <> INTPTR THEN ERROR(125) END ELSE GENLDC(0); GEN2(77(*CXP*),0(*SYS*),15(*FWRR*)) END ELSE IF LSP = CHARPTR THEN BEGIN IF DEFAULT THEN GENLDC(0); GEN2(77(*CXP*),0(*SYS*),17(*FWRC*)) END ELSE IF STRGTYPE(LSP) THEN BEGIN IF DEFAULT THEN GENLDC(0); GEN2(77(*CXP*),0(*SYS*),19(*FWRS*)) END ELSE IF PAOFCHAR(LSP) THEN BEGIN LMAX := 0; IF LSP^.INXTYPE <> NIL THEN BEGIN GETBOUNDS(LSP^.INXTYPE,LMIN,LMAX); LMAX := LMAX - LMIN + 1 END; IF DEFAULT THEN GENLDC(LMAX); GENLDC(LMAX); GEN2(77(*CXP*),0(*SYS*),20(*FWRB*)) END ELSE ERROR(125); IF IOCHECK THEN GEN1(30(*CSP*),0(*IOC*)); TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; END; IF LKEY = 4 THEN (*WRITELN*) BEGIN LOADIDADDR(FILEPTR); GEN2(77(*CXP*),0(*SYS*),22(*FWLN*)); IF IOCHECK THEN GEN1(30(*CSP*),0(*IOC*)) END END (*WRITE*) ; PROCEDURE CALLNONSPECIAL; VAR NXT,LCP: CTP; LSP: STP; LB: BOOLEAN; LMIN,LMAX: INTEGER; BEGIN WITH FCP^ DO BEGIN NXT := NEXT; IF PFDECKIND = DECLARED THEN IF PFKIND <> ACTUAL THEN ERROR(400) END; IF SY = LPARENT THEN BEGIN REPEAT IF NXT = NIL THEN ERROR(126); INSYMBOL; EXPRESSION(FSYS + [COMMA,RPARENT]); IF (GATTR.TYPTR <> NIL) AND (NXT <> NIL) THEN BEGIN LSP := NXT^.IDTYPE; IF LSP <> NIL THEN BEGIN IF NXT^.VKIND = ACTUAL THEN IF GATTR.TYPTR^.FORM <= POWER THEN BEGIN LB := (GATTR.TYPTR = CHARPTR) AND (GATTR.KIND = CST); LOAD; IF LSP^.FORM = POWER THEN GEN1(32(*ADJ*),LSP^.SIZE) ELSE IF (LSP^.FORM = SUBRANGE) AND RANGECHECK THEN BEGIN GENLDC(LSP^.MIN.IVAL); GENLDC(LSP^.MAX.IVAL); GEN0(8(*CHK*)) END ELSE IF (GATTR.TYPTR = INTPTR) AND COMPTYPES(LSP,REALPTR) THEN BEGIN GEN0(10(*FLT*)); GATTR.TYPTR := REALPTR END ELSE IF LB AND STRGTYPE(LSP) THEN GATTR.TYPTR := STRGPTR END ELSE (*FORM > POWER*) BEGIN LB := STRGTYPE(GATTR.TYPTR) AND (GATTR.KIND = CST); LOADADDRESS; IF LB AND PAOFCHAR(LSP) THEN IF NOT LSP^.AISSTRNG THEN BEGIN GEN0(80(*S1P*)); IF LSP^.INXTYPE <> NIL THEN BEGIN GETBOUNDS(LSP^.INXTYPE,LMIN,LMAX); IF LMAX-LMIN+1 <> GATTR.TYPTR^.MAXLENG THEN ERROR(142); END; GATTR.TYPTR := LSP END END ELSE (*VKIND = FORMAL*) IF GATTR.KIND = VARBL THEN BEGIN LOADADDRESS; IF (LSP^.FORM=POWER) THEN IF GATTR.TYPTR^.SIZE <> LSP^.SIZE THEN ERROR(142) END ELSE ERROR(154); IF NOT COMPTYPES(LSP,GATTR.TYPTR) THEN ERROR(142) END END; IF NXT <> NIL THEN NXT := NXT^.NEXT UNTIL SY <> COMMA; IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4) END (*LPARENT*) ; IF NXT <> NIL THEN ERROR(126); WITH FCP^ DO IF PFDECKIND = DECLARED THEN BEGIN IF KLASS = FUNC THEN BEGIN GENLDC(0); GENLDC(0) END; IF PFSEG <> SEG THEN GEN2(77(*CXP*),PFSEG,PFNAME) ELSE IF PFLEV = 0 THEN GEN1(66(*CBP*),PFNAME) ELSE IF PFLEV = LEVEL THEN GEN1(78(*CLP*),PFNAME) ELSE IF PFLEV = 1 THEN GEN1(79(*CGP*),PFNAME) ELSE GEN1(46(*CIP*),PFNAME) END ELSE IF (CSPNUM <> 21) AND (CSPNUM <> 22) THEN GEN1(30(*CSP*),CSPNUM); GATTR.TYPTR := FCP^.IDTYPE END (*CALLNONSPECIAL*) ; BEGIN (*CALL*) IF FCP^.PFDECKIND = SPECIAL THEN BEGIN WASLPARENT := TRUE; LKEY := FCP^.KEY; IF SY = LPARENT THEN INSYMBOL ELSE IF LKEY IN [2,4,5,6] THEN WASLPARENT := FALSE ELSE ERROR(9); IF LKEY IN [7,8,9,10,11,13,14,25,36] THEN BEGIN EXPRESSION(FSYS + [COMMA,RPARENT]); LOAD END; CASE LKEY OF 1,2: READ; 3,4: WRITE; 5,6: BEGIN (*EOF & EOLN*) IF WASLPARENT THEN BEGIN VARIABLE(FSYS + [RPARENT]); LOADADDRESS; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <> FILES THEN ERROR(125) ELSE IF (GATTR.TYPTR^.FILTYPE <> CHARPTR) AND (LKEY = 6) THEN ERROR(399) END ELSE LOADIDADDR(INPUTPTR); GENLDC(0); GENLDC(0); IF LKEY = 5 THEN GEN2(77(*CXP*),0(*SYS*),10(*FEOF*)) ELSE GEN2(77(*CXP*),0(*SYS*),11(*FEOLN*)); GATTR.TYPTR := BOOLPTR END (*EOF*) ; 7,8: BEGIN GENLDC(1); (*PREDSUCC*) IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM = SCALAR THEN IF LKEY = 8 THEN GEN0(2(*ADI*)) ELSE GEN0(21(*SBI*)) ELSE ERROR(115) END (*PREDSUCC*) ; 9: BEGIN (*ORD*) IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM >= POWER THEN ERROR(125); GATTR.TYPTR := INTPTR END (*ORD*) ; 10: BEGIN (*SQR*) IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR = INTPTR THEN GEN0(24(*SQI*)) ELSE IF GATTR.TYPTR = REALPTR THEN GEN0(25(*SQR*)) ELSE BEGIN ERROR(125); GATTR.TYPTR := INTPTR END END (*SQR*) ; 11: BEGIN (*ABS*) IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR = INTPTR THEN GEN0(0(*ABI*)) ELSE IF GATTR.TYPTR = REALPTR THEN GEN0(1(*ABR*)) ELSE BEGIN ERROR(125); GATTR.TYPTR := INTPTR END END (*ABS*) ; 12: NEWSTMT; 13,14: UNITIO; 15: CONCAT; 16: BEGIN (*LENGTH*) STRGVAR(FSYS + [RPARENT],FALSE); GEN0(62(*LDB*)); GATTR.TYPTR := INTPTR END (*LENGTH*) ; 17: BEGIN (*INSERT*) STRGVAR(FSYS + [COMMA],FALSE); IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); STRGVAR(FSYS + [COMMA],TRUE); GENLDC(GATTR.TYPTR^.MAXLENG); IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); EXPRESSION(FSYS + [RPARENT]); LOAD; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR <> INTPTR THEN ERROR(125); GEN2(77(*CXP*),0(*SYS*),24(*SINSERT*)) END (*INSERT*) ; 43,18,19: COPYDELETE; 20: BEGIN (*POS*) STRGVAR(FSYS + [COMMA],FALSE); IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); STRGVAR(FSYS + [RPARENT],FALSE); GENLDC(0); GENLDC(0); GEN2(77(*CXP*),0(*SYS*),27(*SPOS*)); GATTR.TYPTR := INTPTR END (*POS*) ; 27,21,22: MOVE; 23: EXIT; 24: BEGIN (*IDSEARCH*) VARIABLE(FSYS + [COMMA]); LOADADDRESS; IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); VARIABLE(FSYS + [RPARENT]); LOADADDRESS; GEN1(30(*CSP*),7(*IDS*)) END (*IDSEARCH*) ; 25: BEGIN (*TREESEARCH*) IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); VARIABLE(FSYS + [COMMA]); LOADADDRESS; IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); VARIABLE(FSYS + [RPARENT]); LOADADDRESS; GATTR.TYPTR := INTPTR; GEN1(30(*CSP*),8(*TRS*)) END (*TREESEARCH*) ; 26: BEGIN (*TIME*) VARIABLE(FSYS + [COMMA]); LOADADDRESS; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR <> INTPTR THEN ERROR(125); IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); VARIABLE(FSYS + [RPARENT]); LOADADDRESS; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR <> INTPTR THEN ERROR(125); GEN1(30(*CSP*),9(*TIM*)) END (*TIME*) ; 28,29,30: BEGIN (*OPEN*) VARIABLE(FSYS + [COMMA,RPARENT]); LOADADDRESS; IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <> FILES THEN ERROR(125); IF SY = COMMA THEN INSYMBOL ELSE ERROR(20); STRGVAR(FSYS + [RPARENT],FALSE); IF (LKEY = 28) THEN GENLDC(0) ELSE GENLDC(1); GENLDC(0); GEN2(77(*CXP*),0(*SYS*),5(*FOPEN*)) IF IOCHECK THEN GEN1(30(*CSP*),0(*IOC*)) END (*OPEN*) ; 31: CLOSE; 32,33,34,35,40: GETPUTETC; 36: SCAN; 37,38: BLOCKIO; 39,42: DRAWSTUFF; 41: SIZEOF END (*SPECIAL CASES*) ; IF WASLPARENT THEN IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4) END (*SPECIAL PROCEDURES AND FUNCTIONS*) ELSE CALLNONSPECIAL END (*CALL*) ; (*$I XCOMP:E.TEXT *) PROCEDURE EXPRESSION; VAR LATTR: ATTR; LOP: OPERATOR; TYPIND: INTEGER; LSIZE: ADDRRANGE; LSTRING,GSTRING: BOOLEAN; LMIN,LMAX: INTEGER; PROCEDURE FLOATIT(VAR FSP: STP); BEGIN IF GATTR.TYPTR = INTPTR THEN BEGIN GEN0(10(*FLT*)); GATTR.TYPTR := REALPTR END; IF FSP = INTPTR THEN BEGIN GEN0(9(*FLO*)); FSP := REALPTR END END (*FLOATIT*) ; PROCEDURE SIMPLEEXPRESSION(FSYS: SETOFSYS); VAR LATTR: ATTR; LOP: OPERATOR; SIGNED: BOOLEAN; PROCEDURE TERM(FSYS: SETOFSYS); VAR LATTR: ATTR; LOP: OPERATOR; PROCEDURE FACTOR(FSYS: SETOFSYS); VAR LCP: CTP; LVP: CSP; VARPART,ALLCONST: BOOLEAN; LSP: STP; HIGHVAL,LOWVAL,LIC,LOP: INTEGER; CSTPART: SET OF 0..127; BEGIN IF NOT (SY IN FACBEGSYS) THEN BEGIN ERROR(58); SKIP(FSYS + FACBEGSYS); GATTR.TYPTR := NIL END; WHILE SY IN FACBEGSYS DO BEGIN CASE SY OF (*ID*) IDENT: BEGIN SEARCHID([KONST,VARS,FIELD,FUNC],LCP); INSYMBOL; IF LCP^.KLASS = FUNC THEN BEGIN CALL(FSYS,LCP); GATTR.KIND := EXPR END ELSE IF LCP^.KLASS = KONST THEN WITH GATTR, LCP^ DO BEGIN TYPTR := IDTYPE; KIND := CST; CVAL := VALUES END ELSE SELECTOR(FSYS,LCP); IF GATTR.TYPTR <> NIL THEN WITH GATTR,TYPTR^ DO IF FORM = SUBRANGE THEN TYPTR := RANGETYPE END; (*CST*) INTCONST: BEGIN WITH GATTR DO BEGIN TYPTR := INTPTR; KIND := CST; CVAL := VAL END; INSYMBOL END; REALCONST: BEGIN WITH GATTR DO BEGIN TYPTR := REALPTR; KIND := CST; CVAL := VAL END; INSYMBOL END; STRINGCONST: BEGIN WITH GATTR DO BEGIN IF LGTH = 1 THEN TYPTR := CHARPTR ELSE BEGIN NEW(LSP,ARRAYS,TRUE,TRUE); LSP^ := STRGPTR^; LSP^.MAXLENG := LGTH; TYPTR := LSP END; KIND := CST; CVAL := VAL END; INSYMBOL END; (*(*) LPARENT: BEGIN INSYMBOL; EXPRESSION(FSYS + [RPARENT]); IF SY = RPARENT THEN INSYMBOL ELSE ERROR(4) END; (*NOT*) NOTSY: BEGIN INSYMBOL; FACTOR(FSYS); LOAD; GEN0(19(*NOT*)); IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR <> BOOLPTR THEN BEGIN ERROR(135); GATTR.TYPTR := NIL END; END; (*[*) LBRACK: BEGIN INSYMBOL; CSTPART := [ ]; VARPART := FALSE; NEW(LSP,POWER); WITH LSP^ DO BEGIN ELSET := NIL; SIZE := 0; FORM := POWER END; IF SY = RBRACK THEN BEGIN WITH GATTR DO BEGIN TYPTR := LSP; KIND := CST END; INSYMBOL END ELSE BEGIN REPEAT EXPRESSION(FSYS + [COMMA,RBRACK,COLON]); IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <> SCALAR THEN BEGIN ERROR(136); GATTR.TYPTR := NIL END ELSE IF COMPTYPES(LSP^.ELSET,GATTR.TYPTR) THEN BEGIN ALLCONST := FALSE; LOP := 23(*SGS*); IF (GATTR.KIND = CST) AND (GATTR.CVAL.IVAL <= 127) THEN BEGIN ALLCONST := TRUE; LOWVAL := GATTR.CVAL.IVAL; HIGHVAL := LOWVAL END; LIC := IC; LOAD; IF SY = COLON THEN BEGIN INSYMBOL; LOP := 20(*SRS*); EXPRESSION(FSYS + [COMMA,RBRACK]); IF COMPTYPES(LSP^.ELSET,GATTR.TYPTR) THEN ELSE BEGIN ERROR(137); GATTR.TYPTR:=NIL END; IF ALLCONST THEN IF (GATTR.KIND = CST) AND (GATTR.CVAL.IVAL <= 127) THEN HIGHVAL := GATTR.CVAL.IVAL ELSE BEGIN LOAD; ALLCONST := FALSE END ELSE LOAD END; IF ALLCONST THEN BEGIN IC := LIC; (*FORGET FIRST CONST*) CSTPART := CSTPART + [LOWVAL..HIGHVAL] END ELSE BEGIN GEN0(LOP); IF VARPART THEN GEN0(28(*UNI*)) ELSE VARPART := TRUE END; LSP^.ELSET := GATTR.TYPTR; GATTR.TYPTR := LSP END ELSE ERROR(137); TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = RBRACK THEN INSYMBOL ELSE ERROR(12) END; IF VARPART THEN BEGIN IF CSTPART <> [ ] THEN BEGIN SCONST^.PVAL := CSTPART; SCONST^.CCLASS := PSET; GATTR.CVAL.VALP := SCONST; GATTR.KIND := CST; LOAD; GEN0(28(*UNI*)) END; GATTR.KIND := EXPR END ELSE BEGIN SCONST^.PVAL := CSTPART; SCONST^.CCLASS := PSET; GATTR.CVAL.VALP := SCONST; GATTR.KIND := CST END END END (*CASE*) ; IF NOT (SY IN FSYS) THEN BEGIN ERROR(6); SKIP(FSYS + FACBEGSYS) END END (*WHILE*) END (*FACTOR*) ; BEGIN (*TERM*) FACTOR(FSYS + [MULOP]); WHILE SY = MULOP DO BEGIN LOAD; LATTR := GATTR; LOP := OP; INSYMBOL; FACTOR(FSYS + [MULOP]); LOAD; IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN CASE LOP OF (***) MUL: IF (LATTR.TYPTR = INTPTR) AND (GATTR.TYPTR = INTPTR) THEN GEN0(15(*MPI*)) ELSE BEGIN FLOATIT(LATTR.TYPTR); IF (LATTR.TYPTR = REALPTR) AND (GATTR.TYPTR = REALPTR) THEN GEN0(16(*MPR*)) ELSE IF (LATTR.TYPTR^.FORM = POWER) AND COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN GEN0(12(*INT*)) ELSE BEGIN ERROR(134); GATTR.TYPTR:=NIL END END; (*/*) RDIV: BEGIN FLOATIT(LATTR.TYPTR); IF (LATTR.TYPTR = REALPTR) AND (GATTR.TYPTR = REALPTR) THEN GEN0(7(*DVR*)) ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END END; (*DIV*) IDIV: IF (LATTR.TYPTR = INTPTR) AND (GATTR.TYPTR = INTPTR) THEN GEN0(6(*DVI*)) ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END; (*MOD*) IMOD: IF (LATTR.TYPTR = INTPTR) AND (GATTR.TYPTR = INTPTR) THEN GEN0(14(*MOD*)) ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END; (*AND*) ANDOP:IF (LATTR.TYPTR = BOOLPTR) AND (GATTR.TYPTR = BOOLPTR) THEN GEN0(4(*AND*)) ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END END (*CASE*) ELSE GATTR.TYPTR := NIL END (*WHILE*) END (*TERM*) ; BEGIN (*SIMPLEEXPRESSION*) SIGNED := FALSE; IF (SY = ADDOP) AND (OP IN [PLUS,MINUS]) THEN BEGIN SIGNED := OP = MINUS; INSYMBOL END; TERM(FSYS + [ADDOP]); IF SIGNED THEN BEGIN LOAD; IF GATTR.TYPTR = INTPTR THEN GEN0(17(*NGI*)) ELSE IF GATTR.TYPTR = REALPTR THEN GEN0(18(*NGR*)) ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END END; WHILE SY = ADDOP DO BEGIN LOAD; LATTR := GATTR; LOP := OP; INSYMBOL; TERM(FSYS + [ADDOP]); LOAD; IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN CASE LOP OF (*+*) PLUS: IF (LATTR.TYPTR = INTPTR)AND(GATTR.TYPTR = INTPTR) THEN GEN0(2(*ADI*)) ELSE BEGIN FLOATIT(LATTR.TYPTR); IF (LATTR.TYPTR = REALPTR)AND(GATTR.TYPTR = REALPTR) THEN GEN0(3(*ADR*)) ELSE IF (LATTR.TYPTR^.FORM = POWER) AND COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN GEN0(28(*UNI*)) ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END END; (*-*) MINUS: IF (LATTR.TYPTR = INTPTR) AND (GATTR.TYPTR = INTPTR) THEN GEN0(21(*SBI*)) ELSE BEGIN FLOATIT(LATTR.TYPTR); IF (LATTR.TYPTR = REALPTR) AND (GATTR.TYPTR = REALPTR) THEN GEN0(22(*SBR*)) ELSE IF (LATTR.TYPTR^.FORM = POWER) AND COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN GEN0(5(*DIF*)) ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END END; (*OR*) OROP: IF (LATTR.TYPTR = BOOLPTR) AND (GATTR.TYPTR = BOOLPTR) THEN GEN0(13(*IOR*)) ELSE BEGIN ERROR(134); GATTR.TYPTR := NIL END END (*CASE*) ELSE GATTR.TYPTR := NIL END (*WHILE*) END (*SIMPLEEXPRESSION*) ; PROCEDURE MAKEPA(VAR STRGFSP: STP; PAFSP: STP); VAR LMIN,LMAX: INTEGER; BEGIN IF PAFSP^.INXTYPE <> NIL THEN BEGIN GETBOUNDS(PAFSP^.INXTYPE,LMIN,LMAX); IF LMAX-LMIN+1 <> STRGFSP^.MAXLENG THEN ERROR(129) END; STRGFSP := PAFSP END (*MAKEPA*) ; BEGIN (*EXPRESSION*) SIMPLEEXPRESSION(FSYS + [RELOP]); IF SY = RELOP THEN BEGIN LSTRING := (STRGTYPE(GATTR.TYPTR) AND (GATTR.KIND = CST); IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <= POWER THEN LOAD ELSE LOADADDRESS; LATTR := GATTR; LOP := OP; INSYMBOL; SIMPLEEXPRESSION(FSYS); GSTRING := STRGTYPE(GATTR.TYPTR) AND (GATTR.KIND = CST); IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <= POWER THEN LOAD ELSE LOADADDRESS; IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN IF LOP = INOP THEN IF GATTR.TYPTR^.FORM = POWER THEN IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR^.ELSET) THEN GEN0(11(*INN*)) ELSE BEGIN ERROR(129); GATTR.TYPTR := NIL END ELSE BEGIN ERROR(130); GATTR.TYPTR := NIL END ELSE BEGIN IF LATTR.TYPTR <> GATTR.TYPTR THEN FLOATIT(LATTR.TYPTR); IF LSTRING THEN BEGIN IF PAOFCHAR(GATTR.TYPTR) THEN IF NOT GATTR.TYPTR^.AISSTRNG THEN BEGIN GEN0(29(*S2P*)); MAKEPA(LATTR.TYPTR,GATTR.TYPTR) END END ELSE IF GSTRING THEN BEGIN IF PAOFCHAR(LATTR.TYPTR) THEN IF NOT LATTR.TYPTR^.AISSTRNG THEN BEGIN GEN0(80(*S1P*)); MAKEPA(GATTR.TYPTR,LATTR.TYPTR) END; END; IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN BEGIN LSIZE := LATTR.TYPTR^.SIZE; CASE LATTR.TYPTR^.FORM OF SCALAR: IF LATTR.TYPTR = REALPTR THEN TYPIND := 1 ELSE IF LATTR.TYPTR = BOOLPTR THEN TYPIND := 3 ELSE TYPIND := 0; POINTER: BEGIN IF LOP IN [LTOP,LEOP,GTOP,GEOP] THEN ERROR(131); TYPIND := 0 END; POWER: BEGIN IF LOP IN [LTOP,GTOP] THEN ERROR(132); TYPIND := 4 END; ARRAYS: BEGIN TYPIND := 6; IF PAOFCHAR(LATTR.TYPTR) THEN IF LATTR.TYPTR^.AISSTRNG THEN TYPIND := 2 ELSE BEGIN TYPIND := 5; IF LATTR.TYPTR^.INXTYPE <> NIL THEN BEGIN GETBOUNDS(LATTR.TYPTR^.INXTYPE,LMIN,LMAX); LSIZE := LMAX - LMIN + 1 END END ELSE IF LOP IN [LTOP,LEOP,GTOP,GEOP] THEN ERROR(131) END; RECORDS: BEGIN IF LOP IN [LTOP,LEOP,GTOP,GEOP] THEN ERROR(131); TYPIND := 6 END; FILES: BEGIN ERROR(133); TYPIND := 0 END END; CASE LOP OF LTOP: GEN2(53(*LES*),TYPIND,LSIZE); LEOP: GEN2(52(*LEQ*),TYPIND,LSIZE); GTOP: GEN2(49(*GRT*),TYPIND,LSIZE); GEOP: GEN2(48(*GEQ*),TYPIND,LSIZE); NEOP: GEN2(55(*NEQ*),TYPIND,LSIZE); EQOP: GEN2(47(*EQU*),TYPIND,LSIZE) END END ELSE ERROR(129) END; GATTR.TYPTR := BOOLPTR; GATTR.KIND := EXPR END (*SY = RELOP*) END (*EXPRESSION*) ; PROCEDURE STATEMENT(FSYS: SETOFSYS); LABEL 1; VAR LCP: CTP; TTOP: DISPRANGE; LLP: LABELP; HEAP: ^INTEGER; PROCEDURE ASSIGNMENT(FCP: CTP); VAR LATTR: ATTR; CSTRING,PAONLEFT: BOOLEAN; LMIN,LMAX: INTEGER; BEGIN SELECTOR(FSYS + [BECOMES],FCP); IF SY = BECOMES THEN BEGIN LMAX := 0; CSTRING := FALSE; IF GATTR.TYPTR <> NIL THEN IF (GATTR.ACCESS = INDRCT) OR (GATTR.TYPTR^.FORM > POWER) THEN LOADADDRESS; PAONLEFT := PAOFCHAR(GATTR.TYPTR); LATTR := GATTR; INSYMBOL; EXPRESSION(FSYS); IF GATTR.KIND = CST THEN CSTRING := (GATTR.TYPTR = CHARPTR) OR STRGTYPE(GATTR.TYPTR); IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <= POWER THEN LOAD ELSE LOADADDRESS; IF (LATTR.TYPTR <> NIL) AND (GATTR.TYPTR <> NIL) THEN BEGIN IF GATTR.TYPTR = INTPTR THEN IF COMPTYPES(REALPTR,LATTR.TYPTR) THEN BEGIN GEN0(10(*FLT*)); GATTR.TYPTR := REALPTR END; IF PAONLEFT THEN IF LATTR.TYPTR^.AISSTRNG THEN IF CSTRING AND (GATTR.TYPTR = CHARPTR) THEN GATTR.TYPTR := STRGPTR ELSE ELSE IF LATTR.TYPTR^.INXTYPE <> NIL THEN BEGIN GETBOUNDS(LATTR.TYPTR^.INXTYPE,LMIN,LMAX); LMAX := LMAX - LMIN + 1; IF CSTRING AND (GATTR.TYPTR <> CHARPTR) THEN BEGIN GEN0(80(*S1P*)); IF LMAX <> GATTR.TYPTR^.MAXLENG THEN ERROR(129); GATTR.TYPTR := LATTR.TYPTR END END ELSE GATTR.TYPTR := LATTR.TYPTR; IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN CASE LATTR.TYPTR^.FORM OF SUBRANGE: BEGIN IF RANGECHECK THEN BEGIN GENLDC(LATTR.TYPTR^.MIN.IVAL); GENLDC(LATTR.TYPTR^.MAX.IVAL); GEN0(8(*CHK*)) END; STORE(LATTR) END; POWER: BEGIN GEN1(32(*ADJ*),LATTR.TYPTR^.SIZE); STORE(LATTR) END; SCALAR, POINTER: STORE(LATTR); ARRAYS: IF PAONLEFT THEN IF LATTR.TYPTR^.AISSTRNG THEN GEN1(42(*SAS*),LATTR.TYPTR^.MAXLENG) ELSE GEN1(41(*MVB*),LMAX) ELSE GEN1(40(*MOV*),LATTR.TYPTR^.SIZE); RECORDS: GEN1(40(*MOV*),LATTR.TYPTR^.SIZE); FILES: ERROR(146) END ELSE ERROR(129) END END (*SY = BECOMES*) ELSE ERROR(51) END (*ASSIGNMENT*) ; PROCEDURE GOTOSTATEMENT; VAR LLP: LABELP; FOUND: BOOLEAN; TTOP: DISPRANGE; BEGIN IF NOT GOTOOK THEN ERROR(6); IF SY = INTCONST THEN BEGIN FOUND := FALSE; TTOP := TOP; WHILE DISPLAY[TTOP].OCCUR <> BLCK DO TTOP := TTOP - 1; LLP := DISPLAY[TTOP].FLABEL; WHILE (LLP <> NIL) AND NOT FOUND DO WITH LLP^ DO IF LABVAL = VAL.IVAL THEN BEGIN FOUND := TRUE; GENJMP(57(*UJP*),CODELBP) END ELSE LLP := NEXTLAB; IF NOT FOUND THEN ERROR(167); INSYMBOL END ELSE ERROR(15) END (*GOTOSTATEMENT*) ; PROCEDURE COMPOUNDSTATEMENT; BEGIN REPEAT REPEAT STATEMENT(FSYS + [SEMICOLON,ENDSY]) UNTIL NOT (SY IN STATBEGSYS); TEST := SY <> SEMICOLON; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = ENDSY THEN INSYMBOL ELSE ERROR(13) END (*COMPOUNDSTATEMENET*) ; PROCEDURE IFSTATEMENT; VAR LCIX1,LCIX2: LBP; BEGIN EXPRESSION(FSYS + [THENSY]); GENLABEL(LCIX1); GENFJP(LCIX1); IF SY = THENSY THEN INSYMBOL ELSE ERROR(52); STATEMENT(FSYS + [ELSESY]); IF SY = ELSESY THEN BEGIN GENLABEL(LCIX2); GENJMP(57(*UJP*),LCIX2); PUTLABEL(LCIX1); INSYMBOL; STATEMENT(FSYS); PUTLABEL(LCIX2) END ELSE PUTLABEL(LCIX1) END (*IFSTATEMENT*) ; PROCEDURE CASESTATEMENT; LABEL 1; TYPE CIP = ^CASEINFO; CASEINFO = RECORD NEXT: CIP; CSSTART: INTEGER; CSLAB: INTEGER END; VAR LSP,LSP1: STP; FSTPTR,LPT1,LPT2,LPT3: CIP; LVAL: VALU; LADDR, LCIX: LBP; NULSTMT, LMIN, LMAX: INTEGER; BEGIN EXPRESSION(FSYS + [OFSY,COMMA,COLON]); LOAD; GENLABEL(LCIX); GENJMP(57(*UJP*),LCIX); LSP := GATTR.TYPTR; IF LSP <> NIL THEN IF (LSP^.FORM <> SCALAR) OR (LSP = REALPTR) THEN BEGIN ERROR(144); LSP := NIL END; IF SY = OFSY THEN INSYMBOL ELSE ERROR(8); FSTPTR := NIL; GENLABEL(LADDR); REPEAT LPT3 := NIL; REPEAT CONSTANT(FSYS + [COMMA,COLON],LSP1,LVAL); IF LSP <> NIL THEN IF COMPTYPES(LSP,LSP1) THEN BEGIN LPT1 := FSTPTR; LPT2 := NIL; WHILE LPT1 <> NIL DO WITH LPT1^ DO BEGIN IF CSLAB <= LVAL.IVAL THEN BEGIN IF CSLAB = LVAL.IVAL THEN ERROR(156); GOTO 1 END; LPT2 := LPT1; LPT1 := NEXT END; 1: NEW(LPT3); WITH LPT3^ DO BEGIN NEXT := LPT1; CSLAB := LVAL.IVAL; CSSTART := IC END; IF LPT2 = NIL THEN FSTPTR := LPT3 ELSE LPT2^.NEXT := LPT3 END ELSE ERROR(147); TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = COLON THEN INSYMBOL ELSE ERROR(5); REPEAT STATEMENT(FSYS + [SEMICOLON]) UNTIL NOT (SY IN STATBEGSYS); IF LPT3 <> NIL THEN GENJMP(57(*UJP*),LADDR); TEST := SY <> SEMICOLON; IF NOT TEST THEN INSYMBOL UNTIL TEST OR (SY = ENDSY); PUTLABEL(LCIX); IF FSTPTR <> NIL THEN BEGIN LMAX := FSTPTR^.CSLAB; LPT1 := FSTPTR; FSTPTR := NIL; REPEAT LPT2 := LPT1^.NEXT; LPT1^.NEXT := FSTPTR; FSTPTR := LPT1; LPT1 := LPT2 UNTIL LPT1 = NIL; LMIN := FSTPTR^.CSLAB; GEN0(44(*XJP*)); GENWORD(LMIN); GENWORD(LMAX); NULSTMT := IC; GENJMP(57(*UJP*),LADDR); REPEAT WITH FSTPTR^ DO BEGIN WHILE CSLAB > LMIN DO BEGIN GENWORD(IC-NULSTMT); LMIN := LMIN + 1 END; GENWORD(IC-CSSTART); FSTPTR := NEXT; LMIN := LMIN + 1 END UNTIL FSTPTR = NIL; PUTLABEL(LADDR) END; IF SY = ENDSY THEN INSYMBOL ELSE ERROR(13) END (*CASESTATEMENT*) ; PROCEDURE REPEATSTATEMENT; VAR LADDR: LBP; BEGIN GENLABEL(LADDR); PUTLABEL(LADDR); REPEAT REPEAT STATEMENT(FSYS + [SEMICOLON,UNTILSY]) UNTIL NOT (SY IN STATBEGSYS); TEST := SY <> SEMICOLON; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = UNTILSY THEN BEGIN INSYMBOL; EXPRESSION(FSYS); GENFJP(LADDR) END ELSE ERROR(53) END (*REPEATSTATEMENT*) ; PROCEDURE WHILESTATEMENT; VAR LADDR, LCIX: LBP; BEGIN GENLABEL(LADDR); PUTLABEL(LADDR); EXPRESSION(FSYS + [DOSY]); GENLABEL(LCIX); GENFJP(LCIX); IF SY = DOSY THEN INSYMBOL ELSE ERROR(54); STATEMENT(FSYS); GENJMP(57(*UJP*),LADDR); PUTLABEL(LCIX) END (*WHILESTATEMENT*) ; PROCEDURE FORSTATEMENT; VAR LATTR: ATTR; LSP: STP; LSY: SYMBOL; LCIX, LADDR: LBP; BEGIN IF SY = IDENT THEN BEGIN SEARCHID([VARS],LCP); WITH LCP^, LATTR DO BEGIN TYPTR := IDTYPE; KIND := VARBL; IF VKIND = ACTUAL THEN BEGIN ACCESS := DRCT; VLEVEL := VLEV; DPLMT := VADDR END ELSE BEGIN ERROR(155); TYPTR := NIL END END; IF LATTR.TYPTR <> NIL THEN IF (LATTR.TYPTR^.FORM > SUBRANGE) OR COMPTYPES(REALPTR,LATTR.TYPTR) THEN BEGIN ERROR(143); LATTR.TYPTR := NIL END; INSYMBOL END ELSE BEGIN ERROR(2); SKIP(FSYS + [BECOMES,TOSY,DOWNTOSY,DOSY]) END; IF SY = BECOMES THEN BEGIN INSYMBOL; EXPRESSION(FSYS + [TOSY,DOWNTOSY,DOSY]); IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <> SCALAR THEN ERROR(144) ELSE IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN BEGIN LOAD; IF LATTR.TYPTR <> NIL THEN IF (LATTR.TYPTR^.FORM = SUBRANGE) AND RANGECHECK THEN BEGIN GENLDC(LATTR.TYPTR^.MIN.IVAL); GENLDC(LATTR.TYPTR^.MAX.IVAL); GEN0(8(*CHK*)) END; STORE(LATTR) END ELSE ERROR(145) END ELSE BEGIN ERROR(51); SKIP(FSYS + [TOSY,DOWNTOSY,DOSY]) END; GENLABEL(LADDR); IF SY IN [TOSY,DOWNTOSY] THEN BEGIN LSY := SY; INSYMBOL; EXPRESSION(FSYS + [DOSY]); IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM <> SCALAR THEN ERROR(144) ELSE IF COMPTYPES(LATTR.TYPTR,GATTR.TYPTR) THEN BEGIN LOAD; IF LATTR.TYPTR <> NIL THEN IF (LATTR.TYPTR^.FORM = SUBRANGE) AND RANGECHECK THEN BEGIN GENLDC(LATTR.TYPTR^.MIN.IVAL); GENLDC(LATTR.TYPTR^.MAX.IVAL); GEN0(8(*CHK*)) END; GEN2(56(*STR*),0,LC); PUTLABEL(LADDR); GATTR := LATTR; LOAD; GEN2(54(*LOD*),0,LC); LC := LC + INTSIZE; IF LC > LCMAX THEN LCMAX := LC; IF LSY = TOSY THEN GEN2(52(*LEQ*),0,INTSIZE) ELSE GEN2(48(*GEQ*),0,INTSIZE); END ELSE ERROR(145) END ELSE BEGIN ERROR(55); SKIP(FSYS + [DOSY]) END; GENLABEL(LCIX); GENJMP(33(*FJP*),LCIX); IF SY = DOSY THEN INSYMBOL ELSE ERROR(54); STATEMENT(FSYS); GATTR := LATTR; LOAD; GENLDC(1); IF LSY = TOSY THEN GEN0(2(*ADI*)) ELSE GEN0(21(*SBI*)); STORE(LATTR); GENJMP(57(*UJP*),LADDR); PUTLABEL(LCIX); LC := LC - INTSIZE END (*FORSTATEMENT*) ; PROCEDURE WITHSTATEMENT; VAR LCP: CTP; LCNT1,LCNT2: DISPRANGE; BEGIN LCNT1 := 0; LCNT2 := 0; REPEAT IF SY = IDENT THEN BEGIN SEARCHID([VARS,FIELD],LCP); INSYMBOL END ELSE BEGIN ERROR(2); LCP := UVARPTR END; SELECTOR(FSYS + [COMMA,DOSY],LCP); IF GATTR.TYPTR <> NIL THEN IF GATTR.TYPTR^.FORM = RECORDS THEN IF TOP < DISPLIMIT THEN BEGIN TOP := TOP + 1; LCNT1 := LCNT1 + 1; WITH DISPLAY[TOP] DO BEGIN FNAME := GATTR.TYPTR^.FSTFLD END; IF GATTR.ACCESS = DRCT THEN WITH DISPLAY[TOP] DO BEGIN OCCUR := CREC; CLEV := GATTR.VLEVEL; CDSPL := GATTR.DPLMT END ELSE BEGIN LOADADDRESS; GEN2(56(*STR*),0,LC); WITH DISPLAY[TOP] DO BEGIN OCCUR := VREC; VDSPL := LC END; LC := LC + PTRSIZE; LCNT2 := LCNT2 + PTRSIZE; IF LC > LCMAX THEN LCMAX := LC END END ELSE ERROR(250) ELSE ERROR(140); TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = DOSY THEN INSYMBOL ELSE ERROR(54); STATEMENT(FSYS); TOP := TOP - LCNT1; LC := LC - LCNT2; END (*WITHSTATEMENT*) ; BEGIN (*STATEMENT*) IF SY = INTCONST THEN (*LABEL*) BEGIN TTOP := TOP; WHILE DISPLAY[TTOP].OCCUR <> BLCK DO TTOP := TTOP-1; LLP := DISPLAY[TTOP].FLABEL; WHILE LLP <> NIL DO WITH LLP^ DO IF LABVAL = VAL.IVAL THEN BEGIN IF CODELBP^.DEFINED THEN ERROR(165); PUTLABEL(CODELBP); GOTO 1 END ELSE LLP := NEXTLAB; ERROR(167); 1: INSYMBOL; IF SY = COLON THEN INSYMBOL ELSE ERROR(5) END; IF NOT (SY IN FSYS + [IDENT]) THEN BEGIN ERROR(6); SKIP(FSYS) END; IF SY IN STATBEGSYS + [IDENT] THEN BEGIN MARK(HEAP); (*FOR LABEL CLEANUP*) CASE SY OF IDENT: BEGIN SEARCHID([VARS,FIELD,FUNC,PROC],LCP); INSYMBOL; IF LCP^.KLASS = PROC THEN CALL(FSYS,LCP) ELSE ASSIGNMENT(LCP) END; BEGINSY: BEGIN INSYMBOL; COMPOUNDSTATEMENT END; GOTOSY: BEGIN INSYMBOL; GOTOSTATEMENT END; IFSY: BEGIN INSYMBOL; IFSTATEMENT END; CASESY: BEGIN INSYMBOL; CASESTATEMENT END; WHILESY: BEGIN INSYMBOL; WHILESTATEMENT END; REPEATSY: BEGIN INSYMBOL; REPEATSTATEMENT END; FORSY: BEGIN INSYMBOL; FORSTATEMENT END; WITHSY: BEGIN INSYMBOL; WITHSTATEMENT END END; RELEASE(HEAP); IF IC + 100 > MAXCODE THEN BEGIN ERROR(253); IC := 0 END; IF NOT (SY IN [SEMICOLON,ENDSY,ELSESY,UNTILSY]) THEN BEGIN ERROR(6); SKIP(FSYS) END END END (*STATEMENT*) ; (*$I XCOMP:F.TEXT *) PROCEDURE BLOCK(FSYS: SETOFSYS; FSY: SYMBOL; FPROCP: CTP); VAR LSY: SYMBOL; PROCEDURE LABELDECLARATION; VAR LLP: LABELP; REDEF: BOOLEAN; BEGIN REPEAT IF SY = INTCONST THEN WITH DISPLAY[TOP] DO BEGIN LLP := FLABEL; REDEF := FALSE; WHILE (LLP <> NIL) AND NOT REDEF DO IF LLP^.LABVAL <> VAL.IVAL THEN LLP := LLP^.NEXTLAB ELSE BEGIN REDEF := TRUE; ERROR(166) END; IF NOT REDEF THEN BEGIN NEW(LLP); WITH LLP^ DO BEGIN LABVAL := VAL.IVAL; CODELBP := NIL; NEXTLAB := FLABEL END; FLABEL := LLP END; INSYMBOL END ELSE ERROR(15); IF NOT ( SY IN FSYS + [COMMA, SEMICOLON] ) THEN BEGIN ERROR(6); SKIP(FSYS+[COMMA,SEMICOLON]) END; TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14) END (* LABELDECLARATION *) ; PROCEDURE CONSTDECLARATION; VAR LCP: CTP; LSP: STP; LVALU: VALU; BEGIN IF SY <> IDENT THEN BEGIN ERROR(2); SKIP(FSYS + [IDENT]) END; WHILE SY = IDENT DO BEGIN NEW(LCP,KONST); WITH LCP^ DO BEGIN NAME := ID; IDTYPE := NIL; NEXT := NIL; KLASS := KONST END; INSYMBOL; IF (SY = RELOP) AND (OP = EQOP) THEN INSYMBOL ELSE ERROR(16); CONSTANT(FSYS + [SEMICOLON],LSP,LVALU); ENTERID(LCP); LCP^.IDTYPE := LSP; LCP^.VALUES := LVALU; IF SY = SEMICOLON THEN BEGIN INSYMBOL; IF NOT (SY IN FSYS + [IDENT]) THEN BEGIN ERROR(6); SKIP(FSYS + [IDENT]) END END ELSE ERROR(14) END END (*CONSTDECLARATION*) ; PROCEDURE TYPEDECLARATION; VAR LCP,LCP1,LCP2: CTP; LSP: STP; LSIZE: ADDRRANGE; BEGIN IF SY <> IDENT THEN BEGIN ERROR(2); SKIP(FSYS + [IDENT]) END; WHILE SY = IDENT DO BEGIN NEW(LCP,TYPES); WITH LCP^ DO BEGIN NAME := ID; IDTYPE := NIL; KLASS := TYPES END; INSYMBOL; IF (SY = RELOP) AND (OP = EQOP) THEN INSYMBOL ELSE ERROR(16); TYP(FSYS + [SEMICOLON],LSP,LSIZE); ENTERID(LCP); LCP^.IDTYPE := LSP; LCP1 := FWPTR; WHILE LCP1 <> NIL DO BEGIN IF LCP1^.NAME = LCP^.NAME THEN BEGIN LCP1^.IDTYPE^.ELTYPE := LCP^.IDTYPE; IF LCP1 <> FWPTR THEN LCP2^.NEXT := LCP1^.NEXT ELSE FWPTR := LCP1^.NEXT; END; LCP2 := LCP1; LCP1 := LCP1^.NEXT END; IF SY = SEMICOLON THEN BEGIN INSYMBOL; IF NOT (SY IN FSYS + [IDENT]) THEN BEGIN ERROR(6); SKIP(FSYS + [IDENT]) END END ELSE ERROR(14) END; IF FWPTR <> NIL THEN BEGIN ERROR(117); FWPTR := NIL END END (*TYPEDECLARATION*) ; PROCEDURE VARDECLARATION; VAR LCP,NXT,IDLIST: CTP; LSP: STP; LSIZE: ADDRRANGE; BEGIN NXT := NIL; REPEAT REPEAT IF SY = IDENT THEN BEGIN NEW(LCP,VARS); WITH LCP^ DO BEGIN NAME := ID; NEXT := NXT; KLASS := VARS; IDTYPE := NIL; VKIND := ACTUAL; VLEV := LEVEL END; ENTERID(LCP); NXT := LCP; INSYMBOL; END ELSE ERROR(2); IF NOT (SY IN FSYS + [COMMA,COLON] + TYPEDELS) THEN BEGIN ERROR(6); SKIP(FSYS+[COMMA,COLON,SEMICOLON]+TYPEDELS) END; TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = COLON THEN INSYMBOL ELSE ERROR(5); IDLIST := NXT; TYP(FSYS + [SEMICOLON] + TYPEDELS,LSP,LSIZE); WHILE NXT <> NIL DO WITH NXT^ DO BEGIN IDTYPE := LSP; VADDR := LC; LC := LC + LSIZE; NXT := NEXT; IF NEXT = NIL THEN IF LSP <> NIL THEN IF LSP^.FORM = FILES THEN BEGIN (*PUT IDLIST INTO LOCAL FILE LIST*) NEXT := DISPLAY[TOP].FFILE; DISPLAY[TOP].FFILE := IDLIST END END; IF SY = SEMICOLON THEN BEGIN INSYMBOL; IF NOT (SY IN FSYS + [IDENT]) THEN BEGIN ERROR(6); SKIP(FSYS + [IDENT]) END END ELSE ERROR(14) UNTIL (SY <> IDENT) AND NOT (SY IN TYPEDELS); IF FWPTR <> NIL THEN BEGIN ERROR(117); FWPTR := NIL END END (*VARDECLARATION*) ; PROCEDURE PROCDECLARATION(FSY: SYMBOL); VAR OLDLEV: 0..MAXLEVEL; LSY: SYMBOL; LCP,LCP1: CTP; LSP: STP; FORW: BOOLEAN; OLDTOP: DISPRANGE; OLDPROC: PROCRANGE; LLC,LCM: ADDRRANGE; MARKP: ^INTEGER; PROCEDURE PARAMETERLIST(FSY: SETOFSYS; VAR FPAR: CTP; FCP: CTP); VAR LCP,LCP1,LCP2,LCP3: CTP; LSP: STP; LKIND: IDKIND; LLC,LEN : ADDRRANGE; COUNT : INTEGER; BEGIN LCP1 := NIL; LLC := LC; IF NOT (SY IN FSY + [LPARENT]) THEN BEGIN ERROR(7); SKIP(FSYS + FSY + [LPARENT]) END; IF SY = LPARENT THEN BEGIN IF FORW THEN ERROR(119); INSYMBOL; IF NOT (SY IN [IDENT,VARSY]) THEN BEGIN ERROR(7); SKIP(FSYS + [IDENT,RPARENT]) END; WHILE SY IN [IDENT,VARSY] DO BEGIN IF SY = VARSY THEN BEGIN LKIND := FORMAL; INSYMBOL END ELSE LKIND := ACTUAL; LCP2 := NIL; COUNT := 0; REPEAT IF SY = IDENT THEN BEGIN NEW(LCP,VARS); WITH LCP^ DO BEGIN NAME := ID; IDTYPE := NIL; VKIND := LKIND; NEXT := LCP2; KLASS := VARS; VLEV := LEVEL END; ENTERID(LCP); LCP2 := LCP; COUNT := COUNT + 1; INSYMBOL END; IF NOT (SY IN FSYS + [COMMA,COLON]) THEN BEGIN ERROR(7); SKIP(FSYS + [COMMA,SEMICOLON,RPARENT,COLON]) END; TEST := SY <> COMMA; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = COLON THEN BEGIN INSYMBOL; IF SY = IDENT THEN BEGIN SEARCHID([TYPES],LCP); LSP := LCP^.IDTYPE; LCP3 := LCP2; LEN := PTRSIZE; IF LSP <> NIL THEN IF LKIND = ACTUAL THEN IF LSP^.FORM = FILES THEN ERROR(121) ELSE IF LSP^.FORM <= POWER THEN LEN := LSP^.SIZE; LC := LC + COUNT * LEN; WHILE LCP2 <> NIL DO BEGIN LCP := LCP2; WITH LCP2^ DO BEGIN IDTYPE := LSP; LCP2 := NEXT END END; LCP^.NEXT := LCP1; LCP1 := LCP3; INSYMBOL END ELSE ERROR(2); IF NOT (SY IN FSYS + [SEMICOLON,RPARENT]) THEN BEGIN ERROR(7); SKIP(FSYS + [SEMICOLON,RPARENT]) END; END ELSE ERROR(5); IF SY = SEMICOLON THEN BEGIN INSYMBOL; IF NOT (SY IN FSYS + [IDENT,VARSY]) THEN BEGIN ERROR(7); SKIP(FSYS + [IDENT,RPARENT]) END END END (*WHILE*) ; IF SY = RPARENT THEN BEGIN INSYMBOL; IF NOT (SY IN FSY + FSYS) THEN BEGIN ERROR(6); SKIP(FSY + FSYS) END END ELSE ERROR(4); FCP^.LOCALLC := LC; LCP3 := NIL; WHILE LCP1 <> NIL DO WITH LCP1^ DO BEGIN LCP2 := NEXT; NEXT := LCP3; IF (KLASS = VARS) AND (IDTYPE <> NIL) THEN IF (IDTYPE^.FORM <= POWER) OR (VKIND = FORMAL) THEN BEGIN VADDR := LLC; IF VKIND = FORMAL THEN LLC := LLC + PTRSIZE ELSE LLC := LLC + IDTYPE^.SIZE END ELSE BEGIN VADDR := LC; LC := LC + IDTYPE^.SIZE; LLC := LLC + PTRSIZE END; LCP3 := LCP1; LCP1 := LCP2 END; FPAR := LCP3 END ELSE FPAR := NIL END (*PARAMETERLIST*) ; BEGIN (*PROCDECLARATION*) LLC := LC; LC := LCAFTERMARKSTACK; IF FSY = FUNCSY THEN LC := LC + REALSIZE; LINEINFO := LC; DP := TRUE; IF SY = IDENT THEN BEGIN SEARCHSECTION(DISPLAY[TOP].FNAME,LCP); IF LCP <> NIL THEN BEGIN IF LCP^.KLASS = PROC THEN FORW := LCP^.FORWDECL AND (FSY = PROCSY) AND (LCP^.PFKIND = ACTUAL) ELSE IF LCP^.KLASS = FUNC THEN FORW := LCP^.FORWDECL AND (FSY = FUNCSY) AND (LCP^.PFKIND = ACTUAL) ELSE FORW := FALSE; IF NOT FORW THEN ERROR(160) END ELSE FORW := FALSE; IF NOT FORW THEN BEGIN IF FSY = PROCSY THEN NEW(LCP,PROC,DECLARED,ACTUAL) ELSE NEW(LCP,FUNC,DECLARED,ACTUAL); WITH LCP^ DO BEGIN NAME := ID; IDTYPE := NIL; LOCALLC := LC; PFDECKIND := DECLARED; PFKIND := ACTUAL; INSCOPE := FALSE; PFLEV := LEVEL; PFNAME := NEXTPROC; PFSEG := SEG; IF NEXTPROC = MAXPROCNUM THEN ERROR(251) ELSE NEXTPROC := NEXTPROC + 1; IF FSY = PROCSY THEN KLASS := PROC ELSE KLASS := FUNC END; ENTERID(LCP) END ELSE BEGIN LCP1 := LCP^.NEXT; WHILE LCP1 <> NIL DO BEGIN WITH LCP1^ DO IF KLASS = VARS THEN IF IDTYPE <> NIL THEN BEGIN IF VKIND = FORMAL THEN LCM := VADDR + PTRSIZE ELSE LCM := VADDR + IDTYPE^.SIZE; IF LCM > LC THEN LC := LCM END; LCP1 := LCP1^.NEXT END END; INSYMBOL END ELSE BEGIN ERROR(2); LCP := UPRCPTR END; OLDLEV := LEVEL; OLDTOP := TOP; OLDPROC := CURPROC; CURPROC := LCP^.PFNAME; IF LEVEL < MAXLEVEL THEN LEVEL := LEVEL + 1 ELSE ERROR(251); IF TOP < DISPLIMIT THEN BEGIN TOP := TOP + 1; WITH DISPLAY[TOP] DO BEGIN IF FORW THEN FNAME := LCP^.NEXT ELSE FNAME := NIL; FLABEL := NIL; FFILE := NIL; OCCUR := BLCK END END ELSE ERROR(250); IF FSY = PROCSY THEN BEGIN PARAMETERLIST([SEMICOLON],LCP1,LCP); IF NOT FORW THEN LCP^.NEXT := LCP1 END ELSE BEGIN PARAMETERLIST([SEMICOLON,COLON],LCP1,LCP); IF NOT FORW THEN LCP^.NEXT := LCP1; IF SY = COLON THEN BEGIN INSYMBOL; IF SY = IDENT THEN BEGIN IF FORW THEN ERROR(122); SEARCHID([TYPES],LCP1); LSP := LCP1^.IDTYPE; LCP^.IDTYPE := LSP; IF LSP <> NIL THEN IF NOT (LSP^.FORM IN [SCALAR,SUBRANGE,POINTER]) THEN BEGIN ERROR(120); LCP^.IDTYPE := NIL END; INSYMBOL END ELSE BEGIN ERROR(2); SKIP(FSYS + [SEMICOLON]) END END ELSE IF NOT FORW THEN ERROR(123) END; IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14); IF SY = FORWARDSY THEN BEGIN IF FORW THEN ERROR(161) ELSE LCP^.FORWDECL := TRUE; INSYMBOL; IF SY = SEMICOLON THEN INSYMBOL ELSE ERROR(14); IF NOT (SY IN FSYS) THEN BEGIN ERROR(6); SKIP(FSYS) END END ELSE BEGIN MARK(MARKP); WITH LCP^ DO BEGIN FORWDECL := FALSE; INSCOPE := TRUE END; REPEAT BLOCK(FSYS,SEMICOLON,LCP); RELEASE(MARKP); IF SY = SEMICOLON THEN BEGIN INSYMBOL; IF NOT (SY IN [BEGINSY,PROCSY,FUNCSY,PROGSY]) THEN BEGIN ERROR(6); SKIP(FSYS) END END ELSE ERROR(14) UNTIL SY IN [BEGINSY,PROCSY,FUNCSY,PROGSY]; LCP^.INSCOPE := FALSE END; LEVEL := OLDLEV; TOP := OLDTOP; LC := LLC; CURPROC := OLDPROC END (*PROCDECLARATION*) ; PROCEDURE SEGDECLARATION; VAR LSY: SYMBOL; OLDPROC: PROCRANGE; OLDSEG: SEGRANGE; BEGIN IF CODEINSEG THEN BEGIN ERROR(399); SEGINX := 0; CURBYTE := 0 END; OLDSEG := SEG; SEG := NEXTSEG; OLDPROC := NEXTPROC; IF NEXTSEG > MAXSEG THEN ERROR(250) ELSE NEXTSEG := NEXTSEG + 1; NEXTPROC := 1; LSY := SY; IF SY IN [PROCSY,FUNCSY] THEN INSYMBOL ELSE BEGIN ERROR(399); LSY := PROCSY END; IF SY = IDENT THEN SEGTABLE[SEG].SEGNAME := ID; PROCDECLARATION(LSY); IF CODEINSEG THEN FINISHSEG; NEXTPROC := OLDPROC; SEG := OLDSEG END (*SEGDECLARATION*) ; PROCEDURE BODY(FSYS: SETOFSYS); VAR LLC1,EXITIC: ADDRRANGE; LCP,LLCP: CTP; LOP: OPRANGE; LLP: LABELP; LMIN,LMAX: INTEGER; JTINX: JTABRANGE; BEGIN NEXTJTAB := 1; WRITELN(OUTPUT); IF FPROCP = NIL THEN WRITELN(OUTPUT,'SYSTEM') ELSE BEGIN WRITELN(OUTPUT,FPROCP^.NAME); LLC1 := FPROCP^.LOCALLC; LCP := FPROCP^.NEXT; WHILE LCP <> NIL DO WITH LCP^ DO BEGIN IF KLASS = VARS THEN IF IDTYPE <> NIL THEN IF (VKIND = ACTUAL) AND (IDTYPE^.FORM > POWER) THEN BEGIN LLC1 := LLC1 - PTRSIZE; GEN2(50(*LDA*),0,VADDR); GEN2(54(*LOD*),0,LLC1); IF PAOFCHAR(IDTYPE) THEN WITH IDTYPE^ DO IF AISSTRNG THEN GEN1(42(*SAS*),MAXLENG) ELSE IF INXTYPE <> NIL THEN BEGIN GETBOUNDS(INXTYPE,LMIN,LMAX); GEN1(41(*MVB*),LMAX - LMIN + 1) END ELSE ELSE GEN1(40(*MOV*),IDTYPE^.SIZE) END ELSE IF VKIND = FORMAL THEN LLC1 := LLC1 - PTRSIZE ELSE LLC1 := LLC1 - IDTYPE^.SIZE; LCP := NEXT END; END; WRITE(OUTPUT,'<',SCREENDOTS:4,'>'); STARTDOTS := SCREENDOTS; LCMAX := LC; LLP := DISPLAY[TOP].FLABEL; WHILE LLP <> NIL DO BEGIN GENLABEL(LLP^.CODELBP); LLP := LLP^.NEXTLAB END; LCP := DISPLAY[TOP].FFILE; WHILE LCP <> NIL DO WITH LCP^,IDTYPE^ DO BEGIN GEN2(50(*LDA*),0,VADDR); GEN2(50(*LDA*),0,VADDR+FILESIZE); IF FILTYPE = NIL THEN GENLDC(-1) ELSE IF FILTYPE = CHARPTR THEN GENLDC(-2) ELSE GENLDC(FILTYPE^.SIZE); GEN2(77(*CXP*),0(*SYS*),3(*FINIT*)); LCP := NEXT END; REPEAT REPEAT STATEMENT(FSYS + [SEMICOLON,ENDSY]) UNTIL NOT (SY IN STATBEGSYS); TEST := SY <> SEMICOLON; IF NOT TEST THEN INSYMBOL UNTIL TEST; IF SY = ENDSY THEN INSYMBOL ELSE ERROR(13); EXITIC := IC; LCP := DISPLAY[TOP].FFILE; WHILE LCP <> NIL DO WITH LCP^ DO BEGIN GEN2(50(*LDA*),0,VADDR); GENLDC(0); GEN2(77(*CXP*),0(*SYS*),6(*FCLOSE*)); LCP := NEXT END; IF FPROCP = NIL THEN GEN0(86(*XIT*)) ELSE BEGIN IF FPROCP^.PFLEV = 0 THEN LOP := 65(*RBP*) ELSE LOP := 45(*RNP*); IF FPROCP^.IDTYPE = NIL THEN GEN1(LOP,0) ELSE GEN1(LOP,FPROCP^.IDTYPE^.SIZE) END; LLP := DISPLAY[TOP].FLABEL; (* CHECK UNDEFINED LABELS *) WHILE LLP <> NIL DO WITH LLP^,CODELBP^ DO BEGIN IF NOT DEFINED THEN IF REFLIST <> MAXADDR THEN ERROR(168); LLP := NEXTLAB END; JTINX := NEXTJTAB - 1; IF ODD(IC) THEN IC := IC + 1; WHILE JTINX > 0 DO BEGIN GENWORD(IC-JTAB[JTINX]); JTINX := JTINX-1 END; IF FPROCP = NIL THEN BEGIN GENWORD((LCMAX-LCAFTERMARKSTACK)*2); GENWORD(0) END ELSE WITH FPROCP^ DO BEGIN GENWORD((LCMAX-LOCALLC)*2); GENWORD((LOCALLC-LCAFTERMARKSTACK)*2) END; GENWORD(IC-EXITIC); GENWORD(IC); GENBYTE(CURPROC); GENBYTE(LEVEL-1); IF NOT CODEINSEG THEN BEGIN CODEINSEG := TRUE; SEGTABLE[SEG].DISKADDR := CURBLK END; WRITECODE(FALSE); SEGINX := SEGINX + IC; PROCTABLE[CURPROC] := SEGINX - 2 END (*BODY*) ; PROCEDURE FINDFORW(FCP: CTP); BEGIN IF FCP <> NIL THEN WITH FCP^ DO BEGIN IF KLASS IN [PROC,FUNC] THEN IF PFDECKIND = DECLARED THEN IF PFKIND = ACTUAL THEN IF FORWDECL THEN BEGIN USERINFO.ERRNUM := 117; WRITELN(OUTPUT); WRITE(OUTPUT,NAME,' Undefined') END; FINDFORW(RLINK); FINDFORW(LLINK) END END (*FINDFORW*) ; BEGIN (*BLOCK*) REPEAT IF SY = LABELSY THEN BEGIN INSYMBOL; LABELDECLARATION END; IF SY = CONSTSY THEN BEGIN INSYMBOL; CONSTDECLARATION END; IF SY = TYPESY THEN BEGIN INSYMBOL; TYPEDECLARATION END; IF SY = VARSY THEN BEGIN INSYMBOL; VARDECLARATION END; WHILE SY IN [PROCSY,FUNCSY,PROGSY] DO BEGIN LSY := SY; INSYMBOL; IF LSY = PROGSY THEN SEGDECLARATION ELSE PROCDECLARATION(LSY,FALSE) END; IF SY <> BEGINSY THEN IF NOT (INCLUDING AND (SY IN [LABELSY,CONSTSY,TYPESY,VARSY,PROCSY,FUNCSY,PROGSY])) THEN BEGIN ERROR(18); SKIP(FSYS) END UNTIL SY IN STATBEGSYS; DP := FALSE; IC := 0; LINEINFO := 0; IF SY = BEGINSY THEN INSYMBOL ELSE ERROR(17); IF NOT SYSCOMP THEN FINDFORW(DISPLAY[TOP].FNAME); REPEAT BODY(FSYS + [CASESY]); IF SY <> FSY THEN BEGIN ERROR(6); SKIP(FSYS + [FSY]) END UNTIL (SY = FSY) OR (SY IN BLOCKBEGSYS); END (*BLOCK*) ; BEGIN (*COMPILER*) COMPINIT; TIME(LGTH,LOWTIME); BLOCK(BLOCKBEGSYS+STATBEGSYS-[CASESY],PERIOD,OUTERBLOCK); IF SY <> PERIOD THEN ERROR(21); IF LIST THEN BEGIN SCREENDOTS := SCREENDOTS+1; SYMBUFP^[SYMCURSOR] := CHR(EOL); SYMCURSOR := SYMCURSOR+1; PRINTLINE END; FINISHSEG; TIME(LGTH,STARTDOTS); LOWTIME := STARTDOTS-LOWTIME; UNITWRITE(3,IC,7); WRITELN(OUTPUT); WRITE(OUTPUT,SCREENDOTS,' lines'); IF LOWTIME > 0 THEN WRITE(OUTPUT,', ',(LOWTIME+30) DIV 60,' secs, ', ROUND((3600/LOWTIME)*SCREENDOTS),' lines/min'); IC := 0; FOR SEG := 0 TO MAXSEG DO WITH SEGTABLE[SEG] DO BEGIN GENWORD(DISKADDR); GENWORD(CODELENG) END; FOR SEG := 0 TO MAXSEG DO WITH SEGTABLE[SEG] DO FOR LGTH := 1 TO 8 DO GENBYTE(ORD(SEGNAME[LGTH])); CURBLK := 0; CURBYTE := 0; WRITECODE(TRUE) END (*COMPILE*) ; BEGIN END.